voc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-transport-socket.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-transport-socket.c  Socket subclasses of DBusTransport
3  *
4  * Copyright (C) 2002, 2003, 2004, 2006  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
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.
12  *
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.
17  * 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-connection-internal.h"
26 #include "dbus-transport-socket.h"
27 #include "dbus-transport-protected.h"
28 #include "dbus-watch.h"
29
30
31 /**
32  * @defgroup DBusTransportSocket DBusTransport implementations for sockets
33  * @ingroup  DBusInternals
34  * @brief Implementation details of DBusTransport on sockets
35  *
36  * @{
37  */
38
39 /**
40  * Opaque object representing a socket file descriptor transport.
41  */
42 typedef struct DBusTransportSocket DBusTransportSocket;
43
44 /**
45  * Implementation details of DBusTransportSocket. All members are private.
46  */
47 struct DBusTransportSocket
48 {
49   DBusTransport base;                   /**< Parent instance */
50   int fd;                               /**< File descriptor. */
51   DBusWatch *read_watch;                /**< Watch for readability. */
52   DBusWatch *write_watch;               /**< Watch for writability. */
53
54   int max_bytes_read_per_iteration;     /**< To avoid blocking too long. */
55   int max_bytes_written_per_iteration;  /**< To avoid blocking too long. */
56
57   int message_bytes_written;            /**< Number of bytes of current
58                                          *   outgoing message that have
59                                          *   been written.
60                                          */
61   DBusString encoded_outgoing;          /**< Encoded version of current
62                                          *   outgoing message.
63                                          */
64   DBusString encoded_incoming;          /**< Encoded version of current
65                                          *   incoming data.
66                                          */
67 };
68
69 static void
70 free_watches (DBusTransport *transport)
71 {
72   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
73
74   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
75   
76   if (socket_transport->read_watch)
77     {
78       if (transport->connection)
79         _dbus_connection_remove_watch_unlocked (transport->connection,
80                                                 socket_transport->read_watch);
81       _dbus_watch_invalidate (socket_transport->read_watch);
82       _dbus_watch_unref (socket_transport->read_watch);
83       socket_transport->read_watch = NULL;
84     }
85
86   if (socket_transport->write_watch)
87     {
88       if (transport->connection)
89         _dbus_connection_remove_watch_unlocked (transport->connection,
90                                                 socket_transport->write_watch);
91       _dbus_watch_invalidate (socket_transport->write_watch);
92       _dbus_watch_unref (socket_transport->write_watch);
93       socket_transport->write_watch = NULL;
94     }
95
96   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
97 }
98
99 static void
100 socket_finalize (DBusTransport *transport)
101 {
102   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
103
104   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
105   
106   free_watches (transport);
107
108   _dbus_string_free (&socket_transport->encoded_outgoing);
109   _dbus_string_free (&socket_transport->encoded_incoming);
110   
111   _dbus_transport_finalize_base (transport);
112
113   _dbus_assert (socket_transport->read_watch == NULL);
114   _dbus_assert (socket_transport->write_watch == NULL);
115   
116   dbus_free (transport);
117 }
118
119 static void
120 check_write_watch (DBusTransport *transport)
121 {
122   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
123   dbus_bool_t needed;
124
125   if (transport->connection == NULL)
126     return;
127
128   if (transport->disconnected)
129     {
130       _dbus_assert (socket_transport->write_watch == NULL);
131       return;
132     }
133   
134   _dbus_transport_ref (transport);
135
136   if (_dbus_transport_get_is_authenticated (transport))
137     needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
138   else
139     {
140       if (transport->send_credentials_pending)
141         needed = TRUE;
142       else
143         {
144           DBusAuthState auth_state;
145           
146           auth_state = _dbus_auth_do_work (transport->auth);
147           
148           /* If we need memory we install the write watch just in case,
149            * if there's no need for it, it will get de-installed
150            * next time we try reading.
151            */
152           if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
153               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
154             needed = TRUE;
155           else
156             needed = FALSE;
157         }
158     }
159
160   _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
161                  needed, transport->connection, socket_transport->write_watch,
162                  socket_transport->fd,
163                  _dbus_connection_has_messages_to_send_unlocked (transport->connection));
164
165   _dbus_connection_toggle_watch_unlocked (transport->connection,
166                                           socket_transport->write_watch,
167                                           needed);
168
169   _dbus_transport_unref (transport);
170 }
171
172 static void
173 check_read_watch (DBusTransport *transport)
174 {
175   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
176   dbus_bool_t need_read_watch;
177
178   _dbus_verbose ("%s: fd = %d\n",
179                  _DBUS_FUNCTION_NAME, socket_transport->fd);
180   
181   if (transport->connection == NULL)
182     return;
183
184   if (transport->disconnected)
185     {
186       _dbus_assert (socket_transport->read_watch == NULL);
187       return;
188     }
189   
190   _dbus_transport_ref (transport);
191
192   if (_dbus_transport_get_is_authenticated (transport))
193     need_read_watch =
194       _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
195   else
196     {
197       if (transport->receive_credentials_pending)
198         need_read_watch = TRUE;
199       else
200         {
201           /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
202            * is to avoid spinning on the file descriptor when we're waiting
203            * to write or for some other part of the auth process
204            */
205           DBusAuthState auth_state;
206           
207           auth_state = _dbus_auth_do_work (transport->auth);
208
209           /* If we need memory we install the read watch just in case,
210            * if there's no need for it, it will get de-installed
211            * next time we try reading. If we're authenticated we
212            * install it since we normally have it installed while
213            * authenticated.
214            */
215           if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
216               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
217               auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
218             need_read_watch = TRUE;
219           else
220             need_read_watch = FALSE;
221         }
222     }
223
224   _dbus_verbose ("  setting read watch enabled = %d\n", need_read_watch);
225   _dbus_connection_toggle_watch_unlocked (transport->connection,
226                                           socket_transport->read_watch,
227                                           need_read_watch);
228
229   _dbus_transport_unref (transport);
230 }
231
232 static void
233 do_io_error (DBusTransport *transport)
234 {
235   _dbus_transport_ref (transport);
236   _dbus_transport_disconnect (transport);
237   _dbus_transport_unref (transport);
238 }
239
240 /* return value is whether we successfully read any new data. */
241 static dbus_bool_t
242 read_data_into_auth (DBusTransport *transport,
243                      dbus_bool_t   *oom)
244 {
245   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
246   DBusString *buffer;
247   int bytes_read;
248   
249   *oom = FALSE;
250
251   _dbus_auth_get_buffer (transport->auth, &buffer);
252   
253   bytes_read = _dbus_read_socket (socket_transport->fd,
254                                   buffer, socket_transport->max_bytes_read_per_iteration);
255
256   _dbus_auth_return_buffer (transport->auth, buffer,
257                             bytes_read > 0 ? bytes_read : 0);
258
259   if (bytes_read > 0)
260     {
261       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
262
263       return TRUE;
264     }
265   else if (bytes_read < 0)
266     {
267       /* EINTR already handled for us */
268
269       if (errno == ENOMEM)
270         {
271           *oom = TRUE;
272         }
273       else if (errno == EAGAIN ||
274                errno == EWOULDBLOCK)
275         ; /* do nothing, just return FALSE below */
276       else
277         {
278           _dbus_verbose ("Error reading from remote app: %s\n",
279                          _dbus_strerror (errno));
280           do_io_error (transport);
281         }
282
283       return FALSE;
284     }
285   else
286     {
287       _dbus_assert (bytes_read == 0);
288       
289       _dbus_verbose ("Disconnected from remote app\n");
290       do_io_error (transport);
291
292       return FALSE;
293     }
294 }
295
296 /* Return value is whether we successfully wrote any bytes */
297 static dbus_bool_t
298 write_data_from_auth (DBusTransport *transport)
299 {
300   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
301   int bytes_written;
302   const DBusString *buffer;
303
304   if (!_dbus_auth_get_bytes_to_send (transport->auth,
305                                      &buffer))
306     return FALSE;
307   
308   bytes_written = _dbus_write_socket (socket_transport->fd,
309                                       buffer,
310                                       0, _dbus_string_get_length (buffer));
311
312   if (bytes_written > 0)
313     {
314       _dbus_auth_bytes_sent (transport->auth, bytes_written);
315       return TRUE;
316     }
317   else if (bytes_written < 0)
318     {
319       /* EINTR already handled for us */
320       
321       if (errno == EAGAIN ||
322           errno == EWOULDBLOCK)
323         ;
324       else
325         {
326           _dbus_verbose ("Error writing to remote app: %s\n",
327                          _dbus_strerror (errno));
328           do_io_error (transport);
329         }
330     }
331
332   return FALSE;
333 }
334
335 static void
336 exchange_credentials (DBusTransport *transport,
337                       dbus_bool_t    do_reading,
338                       dbus_bool_t    do_writing)
339 {
340   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
341
342   if (do_writing && transport->send_credentials_pending)
343     {
344       if (_dbus_send_credentials_unix_socket (socket_transport->fd,
345                                               NULL))
346         {
347           transport->send_credentials_pending = FALSE;
348         }
349       else
350         {
351           _dbus_verbose ("Failed to write credentials\n");
352           do_io_error (transport);
353         }
354     }
355   
356   if (do_reading && transport->receive_credentials_pending)
357     {
358       if (_dbus_read_credentials_unix_socket (socket_transport->fd,
359                                               &transport->credentials,
360                                               NULL))
361         {
362           transport->receive_credentials_pending = FALSE;
363         }
364       else
365         {
366           _dbus_verbose ("Failed to read credentials\n");
367           do_io_error (transport);
368         }
369     }
370
371   if (!(transport->send_credentials_pending ||
372         transport->receive_credentials_pending))
373     {
374       _dbus_auth_set_credentials (transport->auth,
375                                   &transport->credentials);
376     }
377 }
378
379 static dbus_bool_t
380 do_authentication (DBusTransport *transport,
381                    dbus_bool_t    do_reading,
382                    dbus_bool_t    do_writing,
383                    dbus_bool_t   *auth_completed)
384 {
385   dbus_bool_t oom;
386   dbus_bool_t orig_auth_state;
387
388   oom = FALSE;
389   
390   orig_auth_state = _dbus_transport_get_is_authenticated (transport);
391
392   /* This is essential to avoid the check_write_watch() at the end,
393    * we don't want to add a write watch in do_iteration before
394    * we try writing and get EAGAIN
395    */
396   if (orig_auth_state)
397     {
398       if (auth_completed)
399         *auth_completed = FALSE;
400       return TRUE;
401     }
402   
403   _dbus_transport_ref (transport);
404   
405   while (!_dbus_transport_get_is_authenticated (transport) &&
406          _dbus_transport_get_is_connected (transport))
407     {      
408       exchange_credentials (transport, do_reading, do_writing);
409       
410       if (transport->send_credentials_pending ||
411           transport->receive_credentials_pending)
412         {
413           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
414                          transport->send_credentials_pending,
415                          transport->receive_credentials_pending);
416           goto out;
417         }
418
419 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
420       switch (_dbus_auth_do_work (transport->auth))
421         {
422         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
423           _dbus_verbose (" %s auth state: waiting for input\n",
424                          TRANSPORT_SIDE (transport));
425           if (!do_reading || !read_data_into_auth (transport, &oom))
426             goto out;
427           break;
428       
429         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
430           _dbus_verbose (" %s auth state: waiting for memory\n",
431                          TRANSPORT_SIDE (transport));
432           oom = TRUE;
433           goto out;
434           break;
435       
436         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
437           _dbus_verbose (" %s auth state: bytes to send\n",
438                          TRANSPORT_SIDE (transport));
439           if (!do_writing || !write_data_from_auth (transport))
440             goto out;
441           break;
442       
443         case DBUS_AUTH_STATE_NEED_DISCONNECT:
444           _dbus_verbose (" %s auth state: need to disconnect\n",
445                          TRANSPORT_SIDE (transport));
446           do_io_error (transport);
447           break;
448       
449         case DBUS_AUTH_STATE_AUTHENTICATED:
450           _dbus_verbose (" %s auth state: authenticated\n",
451                          TRANSPORT_SIDE (transport));
452           break;
453         }
454     }
455
456  out:
457   if (auth_completed)
458     *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
459   
460   check_read_watch (transport);
461   check_write_watch (transport);
462   _dbus_transport_unref (transport);
463
464   if (oom)
465     return FALSE;
466   else
467     return TRUE;
468 }
469
470 /* returns false on oom */
471 static dbus_bool_t
472 do_writing (DBusTransport *transport)
473 {
474   int total;
475   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
476   dbus_bool_t oom;
477   
478   /* No messages without authentication! */
479   if (!_dbus_transport_get_is_authenticated (transport))
480     {
481       _dbus_verbose ("Not authenticated, not writing anything\n");
482       return TRUE;
483     }
484
485   if (transport->disconnected)
486     {
487       _dbus_verbose ("Not connected, not writing anything\n");
488       return TRUE;
489     }
490
491 #if 1
492   _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
493                  _dbus_connection_has_messages_to_send_unlocked (transport->connection),
494                  socket_transport->fd);
495 #endif
496   
497   oom = FALSE;
498   total = 0;
499
500   while (!transport->disconnected &&
501          _dbus_connection_has_messages_to_send_unlocked (transport->connection))
502     {
503       int bytes_written;
504       DBusMessage *message;
505       const DBusString *header;
506       const DBusString *body;
507       int header_len, body_len;
508       int total_bytes_to_write;
509       
510       if (total > socket_transport->max_bytes_written_per_iteration)
511         {
512           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
513                          total, socket_transport->max_bytes_written_per_iteration);
514           goto out;
515         }
516       
517       message = _dbus_connection_get_message_to_send (transport->connection);
518       _dbus_assert (message != NULL);
519       _dbus_message_lock (message);
520
521 #if 0
522       _dbus_verbose ("writing message %p\n", message);
523 #endif
524       
525       _dbus_message_get_network_data (message,
526                                       &header, &body);
527
528       header_len = _dbus_string_get_length (header);
529       body_len = _dbus_string_get_length (body);
530
531       if (_dbus_auth_needs_encoding (transport->auth))
532         {
533           if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
534             {
535               if (!_dbus_auth_encode_data (transport->auth,
536                                            header, &socket_transport->encoded_outgoing))
537                 {
538                   oom = TRUE;
539                   goto out;
540                 }
541               
542               if (!_dbus_auth_encode_data (transport->auth,
543                                            body, &socket_transport->encoded_outgoing))
544                 {
545                   _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
546                   oom = TRUE;
547                   goto out;
548                 }
549             }
550           
551           total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
552
553 #if 0
554           _dbus_verbose ("encoded message is %d bytes\n",
555                          total_bytes_to_write);
556 #endif
557           
558           bytes_written =
559             _dbus_write_socket (socket_transport->fd,
560                                 &socket_transport->encoded_outgoing,
561                                 socket_transport->message_bytes_written,
562                                 total_bytes_to_write - socket_transport->message_bytes_written);
563         }
564       else
565         {
566           total_bytes_to_write = header_len + body_len;
567
568 #if 0
569           _dbus_verbose ("message is %d bytes\n",
570                          total_bytes_to_write);          
571 #endif
572           
573           if (socket_transport->message_bytes_written < header_len)
574             {
575               bytes_written =
576                 _dbus_write_socket_two (socket_transport->fd,
577                                         header,
578                                         socket_transport->message_bytes_written,
579                                         header_len - socket_transport->message_bytes_written,
580                                         body,
581                                         0, body_len);
582             }
583           else
584             {
585               bytes_written =
586                 _dbus_write_socket (socket_transport->fd,
587                                     body,
588                                     (socket_transport->message_bytes_written - header_len),
589                                     body_len -
590                                     (socket_transport->message_bytes_written - header_len));
591             }
592         }
593
594       if (bytes_written < 0)
595         {
596           /* EINTR already handled for us */
597           
598           if (errno == EAGAIN ||
599               errno == EWOULDBLOCK)
600             goto out;
601           else
602             {
603               _dbus_verbose ("Error writing to remote app: %s\n",
604                              _dbus_strerror (errno));
605               do_io_error (transport);
606               goto out;
607             }
608         }
609       else
610         {
611           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
612                          total_bytes_to_write);
613           
614           total += bytes_written;
615           socket_transport->message_bytes_written += bytes_written;
616
617           _dbus_assert (socket_transport->message_bytes_written <=
618                         total_bytes_to_write);
619           
620           if (socket_transport->message_bytes_written == total_bytes_to_write)
621             {
622               socket_transport->message_bytes_written = 0;
623               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
624
625               _dbus_connection_message_sent (transport->connection,
626                                              message);
627             }
628         }
629     }
630
631  out:
632   if (oom)
633     return FALSE;
634   else
635     return TRUE;
636 }
637
638 /* returns false on out-of-memory */
639 static dbus_bool_t
640 do_reading (DBusTransport *transport)
641 {
642   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
643   DBusString *buffer;
644   int bytes_read;
645   int total;
646   dbus_bool_t oom;
647
648   _dbus_verbose ("%s: fd = %d\n", _DBUS_FUNCTION_NAME,
649                  socket_transport->fd);
650   
651   /* No messages without authentication! */
652   if (!_dbus_transport_get_is_authenticated (transport))
653     return TRUE;
654
655   oom = FALSE;
656   
657   total = 0;
658
659  again:
660   
661   /* See if we've exceeded max messages and need to disable reading */
662   check_read_watch (transport);
663   
664   if (total > socket_transport->max_bytes_read_per_iteration)
665     {
666       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
667                      total, socket_transport->max_bytes_read_per_iteration);
668       goto out;
669     }
670
671   _dbus_assert (socket_transport->read_watch != NULL ||
672                 transport->disconnected);
673   
674   if (transport->disconnected)
675     goto out;
676
677   if (!dbus_watch_get_enabled (socket_transport->read_watch))
678     return TRUE;
679   
680   if (_dbus_auth_needs_decoding (transport->auth))
681     {
682       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
683         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
684       else
685         bytes_read = _dbus_read_socket (socket_transport->fd,
686                                         &socket_transport->encoded_incoming,
687                                         socket_transport->max_bytes_read_per_iteration);
688
689       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
690                     bytes_read);
691       
692       if (bytes_read > 0)
693         {
694           int orig_len;
695           
696           _dbus_message_loader_get_buffer (transport->loader,
697                                            &buffer);
698
699           orig_len = _dbus_string_get_length (buffer);
700           
701           if (!_dbus_auth_decode_data (transport->auth,
702                                        &socket_transport->encoded_incoming,
703                                        buffer))
704             {
705               _dbus_verbose ("Out of memory decoding incoming data\n");
706               oom = TRUE;
707               goto out;
708             }
709
710           _dbus_message_loader_return_buffer (transport->loader,
711                                               buffer,
712                                               _dbus_string_get_length (buffer) - orig_len);
713
714           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
715         }
716     }
717   else
718     {
719       _dbus_message_loader_get_buffer (transport->loader,
720                                        &buffer);
721       
722       bytes_read = _dbus_read_socket (socket_transport->fd,
723                                       buffer, socket_transport->max_bytes_read_per_iteration);
724       
725       _dbus_message_loader_return_buffer (transport->loader,
726                                           buffer,
727                                           bytes_read < 0 ? 0 : bytes_read);
728     }
729   
730   if (bytes_read < 0)
731     {
732       /* EINTR already handled for us */
733
734       if (errno == ENOMEM)
735         {
736           _dbus_verbose ("Out of memory in read()/do_reading()\n");
737           oom = TRUE;
738           goto out;
739         }
740       else if (errno == EAGAIN ||
741                errno == EWOULDBLOCK)
742         goto out;
743       else
744         {
745           _dbus_verbose ("Error reading from remote app: %s\n",
746                          _dbus_strerror (errno));
747           do_io_error (transport);
748           goto out;
749         }
750     }
751   else if (bytes_read == 0)
752     {
753       _dbus_verbose ("Disconnected from remote app\n");
754       do_io_error (transport);
755       goto out;
756     }
757   else
758     {
759       _dbus_verbose (" read %d bytes\n", bytes_read);
760       
761       total += bytes_read;      
762
763       if (!_dbus_transport_queue_messages (transport))
764         {
765           oom = TRUE;
766           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
767           goto out;
768         }
769       
770       /* Try reading more data until we get EAGAIN and return, or
771        * exceed max bytes per iteration.  If in blocking mode of
772        * course we'll block instead of returning.
773        */
774       goto again;
775     }
776
777  out:
778   if (oom)
779     return FALSE;
780   else
781     return TRUE;
782 }
783
784 static dbus_bool_t
785 socket_handle_watch (DBusTransport *transport,
786                    DBusWatch     *watch,
787                    unsigned int   flags)
788 {
789   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
790
791   _dbus_assert (watch == socket_transport->read_watch ||
792                 watch == socket_transport->write_watch);
793   _dbus_assert (watch != NULL);
794   
795   /* Disconnect in case of an error.  In case of hangup do not
796    * disconnect the transport because data can still be in the buffer
797    * and do_reading may need several iteration to read it all (because
798    * of its max_bytes_read_per_iteration limit).  The condition where
799    * flags == HANGUP (without READABLE) probably never happen in fact.
800    */
801   if ((flags & DBUS_WATCH_ERROR) ||
802       ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE)))
803     {
804       _dbus_verbose ("Hang up or error on watch\n");
805       _dbus_transport_disconnect (transport);
806       return TRUE;
807     }
808   
809   if (watch == socket_transport->read_watch &&
810       (flags & DBUS_WATCH_READABLE))
811     {
812       dbus_bool_t auth_finished;
813 #if 1
814       _dbus_verbose ("handling read watch %p flags = %x\n",
815                      watch, flags);
816 #endif
817       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
818         return FALSE;
819
820       /* We don't want to do a read immediately following
821        * a successful authentication.  This is so we
822        * have a chance to propagate the authentication
823        * state further up.  Specifically, we need to
824        * process any pending data from the auth object.
825        */
826       if (!auth_finished)
827         {
828           if (!do_reading (transport))
829             {
830               _dbus_verbose ("no memory to read\n");
831               return FALSE;
832             }
833         }
834       else
835         {
836           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
837         }
838     }
839   else if (watch == socket_transport->write_watch &&
840            (flags & DBUS_WATCH_WRITABLE))
841     {
842 #if 1
843       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
844                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
845 #endif
846       if (!do_authentication (transport, FALSE, TRUE, NULL))
847         return FALSE;
848       
849       if (!do_writing (transport))
850         {
851           _dbus_verbose ("no memory to write\n");
852           return FALSE;
853         }
854
855       /* See if we still need the write watch */
856       check_write_watch (transport);
857     }
858 #ifdef DBUS_ENABLE_VERBOSE_MODE
859   else
860     {
861       if (watch == socket_transport->read_watch)
862         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
863                        flags);
864       else if (watch == socket_transport->write_watch)
865         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
866                        flags);
867       else
868         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
869                        watch, dbus_watch_get_fd (watch));
870     }
871 #endif /* DBUS_ENABLE_VERBOSE_MODE */
872
873   return TRUE;
874 }
875
876 static void
877 socket_disconnect (DBusTransport *transport)
878 {
879   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
880
881   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
882   
883   free_watches (transport);
884   
885   _dbus_close_socket (socket_transport->fd, NULL);
886   socket_transport->fd = -1;
887 }
888
889 static dbus_bool_t
890 socket_connection_set (DBusTransport *transport)
891 {
892   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
893
894   _dbus_watch_set_handler (socket_transport->write_watch,
895                            _dbus_connection_handle_watch,
896                            transport->connection, NULL);
897
898   _dbus_watch_set_handler (socket_transport->read_watch,
899                            _dbus_connection_handle_watch,
900                            transport->connection, NULL);
901   
902   if (!_dbus_connection_add_watch_unlocked (transport->connection,
903                                             socket_transport->write_watch))
904     return FALSE;
905
906   if (!_dbus_connection_add_watch_unlocked (transport->connection,
907                                             socket_transport->read_watch))
908     {
909       _dbus_connection_remove_watch_unlocked (transport->connection,
910                                               socket_transport->write_watch);
911       return FALSE;
912     }
913
914   check_read_watch (transport);
915   check_write_watch (transport);
916
917   return TRUE;
918 }
919
920 /**
921  * @todo We need to have a way to wake up the select sleep if
922  * a new iteration request comes in with a flag (read/write) that
923  * we're not currently serving. Otherwise a call that just reads
924  * could block a write call forever (if there are no incoming
925  * messages).
926  */
927 static  void
928 socket_do_iteration (DBusTransport *transport,
929                    unsigned int   flags,
930                    int            timeout_milliseconds)
931 {
932   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
933   DBusPollFD poll_fd;
934   int poll_res;
935   int poll_timeout;
936
937   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
938                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
939                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
940                  timeout_milliseconds,
941                  socket_transport->read_watch,
942                  socket_transport->write_watch,
943                  socket_transport->fd);
944   
945   /* the passed in DO_READING/DO_WRITING flags indicate whether to
946    * read/write messages, but regardless of those we may need to block
947    * for reading/writing to do auth.  But if we do reading for auth,
948    * we don't want to read any messages yet if not given DO_READING.
949    */
950
951   poll_fd.fd = socket_transport->fd;
952   poll_fd.events = 0;
953   
954   if (_dbus_transport_get_is_authenticated (transport))
955     {
956       /* This is kind of a hack; if we have stuff to write, then try
957        * to avoid the poll. This is probably about a 5% speedup on an
958        * echo client/server.
959        *
960        * If both reading and writing were requested, we want to avoid this
961        * since it could have funky effects:
962        *   - both ends spinning waiting for the other one to read
963        *     data so they can finish writing
964        *   - prioritizing all writing ahead of reading
965        */
966       if ((flags & DBUS_ITERATION_DO_WRITING) &&
967           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
968           !transport->disconnected &&
969           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
970         {
971           do_writing (transport);
972
973           if (transport->disconnected ||
974               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
975             goto out;
976         }
977
978       /* If we get here, we decided to do the poll() after all */
979       _dbus_assert (socket_transport->read_watch);
980       if (flags & DBUS_ITERATION_DO_READING)
981         poll_fd.events |= _DBUS_POLLIN;
982
983       _dbus_assert (socket_transport->write_watch);
984       if (flags & DBUS_ITERATION_DO_WRITING)
985         poll_fd.events |= _DBUS_POLLOUT;
986     }
987   else
988     {
989       DBusAuthState auth_state;
990       
991       auth_state = _dbus_auth_do_work (transport->auth);
992
993       if (transport->receive_credentials_pending ||
994           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
995         poll_fd.events |= _DBUS_POLLIN;
996
997       if (transport->send_credentials_pending ||
998           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
999         poll_fd.events |= _DBUS_POLLOUT;
1000     }
1001
1002   if (poll_fd.events)
1003     {
1004       if (flags & DBUS_ITERATION_BLOCK)
1005         poll_timeout = timeout_milliseconds;
1006       else
1007         poll_timeout = 0;
1008
1009       /* For blocking selects we drop the connection lock here
1010        * to avoid blocking out connection access during a potentially
1011        * indefinite blocking call. The io path is still protected
1012        * by the io_path_cond condvar, so we won't reenter this.
1013        */
1014       if (flags & DBUS_ITERATION_BLOCK)
1015         {
1016           _dbus_verbose ("unlock %s pre poll\n", _DBUS_FUNCTION_NAME);
1017           _dbus_connection_unlock (transport->connection);
1018         }
1019       
1020     again:
1021       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
1022
1023       if (poll_res < 0 && errno == EINTR)
1024         goto again;
1025
1026       if (flags & DBUS_ITERATION_BLOCK)
1027         {
1028           _dbus_verbose ("lock %s post poll\n", _DBUS_FUNCTION_NAME);
1029           _dbus_connection_lock (transport->connection);
1030         }
1031       
1032       if (poll_res >= 0)
1033         {
1034           if (poll_res == 0)
1035             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
1036                                   * valgrind flags it as an error. though it probably
1037                                   * is guaranteed on linux at least.
1038                                   */
1039           
1040           if (poll_fd.revents & _DBUS_POLLERR)
1041             do_io_error (transport);
1042           else
1043             {
1044               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
1045               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
1046               dbus_bool_t authentication_completed;
1047
1048               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
1049                              need_read, need_write);
1050               do_authentication (transport, need_read, need_write,
1051                                  &authentication_completed);
1052
1053               /* See comment in socket_handle_watch. */
1054               if (authentication_completed)
1055                 goto out;
1056                                  
1057               if (need_read && (flags & DBUS_ITERATION_DO_READING))
1058                 do_reading (transport);
1059               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
1060                 do_writing (transport);
1061             }
1062         }
1063       else
1064         {
1065           _dbus_verbose ("Error from _dbus_poll(): %s\n",
1066                          _dbus_strerror (errno));
1067         }
1068     }
1069
1070
1071  out:
1072   /* We need to install the write watch only if we did not
1073    * successfully write everything. Note we need to be careful that we
1074    * don't call check_write_watch *before* do_writing, since it's
1075    * inefficient to add the write watch, and we can avoid it most of
1076    * the time since we can write immediately.
1077    * 
1078    * However, we MUST always call check_write_watch(); DBusConnection code
1079    * relies on the fact that running an iteration will notice that
1080    * messages are pending.
1081    */
1082   check_write_watch (transport);
1083
1084   _dbus_verbose (" ... leaving do_iteration()\n");
1085 }
1086
1087 static void
1088 socket_live_messages_changed (DBusTransport *transport)
1089 {
1090   /* See if we should look for incoming messages again */
1091   check_read_watch (transport);
1092 }
1093
1094
1095 static dbus_bool_t
1096 socket_get_socket_fd (DBusTransport *transport,
1097                       int           *fd_p)
1098 {
1099   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1100   
1101   *fd_p = socket_transport->fd;
1102   
1103   return TRUE;
1104 }
1105
1106 static const DBusTransportVTable socket_vtable = {
1107   socket_finalize,
1108   socket_handle_watch,
1109   socket_disconnect,
1110   socket_connection_set,
1111   socket_do_iteration,
1112   socket_live_messages_changed,
1113   socket_get_socket_fd
1114 };
1115
1116 /**
1117  * Creates a new transport for the given socket file descriptor.  The file
1118  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1119  * make it so). This function is shared by various transports that
1120  * boil down to a full duplex file descriptor.
1121  *
1122  * @param fd the file descriptor.
1123  * @param server_guid non-#NULL if this transport is on the server side of a connection
1124  * @param address the transport's address
1125  * @returns the new transport, or #NULL if no memory.
1126  */
1127 DBusTransport*
1128 _dbus_transport_new_for_socket (int               fd,
1129                                 const DBusString *server_guid,
1130                                 const DBusString *address)
1131 {
1132   DBusTransportSocket *socket_transport;
1133   
1134   socket_transport = dbus_new0 (DBusTransportSocket, 1);
1135   if (socket_transport == NULL)
1136     return NULL;
1137
1138   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
1139     goto failed_0;
1140
1141   if (!_dbus_string_init (&socket_transport->encoded_incoming))
1142     goto failed_1;
1143   
1144   socket_transport->write_watch = _dbus_watch_new (fd,
1145                                                  DBUS_WATCH_WRITABLE,
1146                                                  FALSE,
1147                                                  NULL, NULL, NULL);
1148   if (socket_transport->write_watch == NULL)
1149     goto failed_2;
1150   
1151   socket_transport->read_watch = _dbus_watch_new (fd,
1152                                                 DBUS_WATCH_READABLE,
1153                                                 FALSE,
1154                                                 NULL, NULL, NULL);
1155   if (socket_transport->read_watch == NULL)
1156     goto failed_3;
1157   
1158   if (!_dbus_transport_init_base (&socket_transport->base,
1159                                   &socket_vtable,
1160                                   server_guid, address))
1161     goto failed_4;
1162   
1163   socket_transport->fd = fd;
1164   socket_transport->message_bytes_written = 0;
1165   
1166   /* These values should probably be tunable or something. */     
1167   socket_transport->max_bytes_read_per_iteration = 2048;
1168   socket_transport->max_bytes_written_per_iteration = 2048;
1169   
1170   return (DBusTransport*) socket_transport;
1171
1172  failed_4:
1173   _dbus_watch_unref (socket_transport->read_watch);
1174  failed_3:
1175   _dbus_watch_unref (socket_transport->write_watch);
1176  failed_2:
1177   _dbus_string_free (&socket_transport->encoded_incoming);
1178  failed_1:
1179   _dbus_string_free (&socket_transport->encoded_outgoing);
1180  failed_0:
1181   dbus_free (socket_transport);
1182   return NULL;
1183 }
1184
1185 /**
1186  * Creates a new transport for the given hostname and port.
1187  *
1188  * @param host the host to connect to
1189  * @param port the port to connect to
1190  * @param error location to store reason for failure.
1191  * @returns a new transport, or #NULL on failure.
1192  */
1193 DBusTransport*
1194 _dbus_transport_new_for_tcp_socket (const char     *host,
1195                                     dbus_int32_t    port,
1196                                     DBusError      *error)
1197 {
1198   int fd;
1199   DBusTransport *transport;
1200   DBusString address;
1201   
1202   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1203
1204   if (!_dbus_string_init (&address))
1205     {
1206       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1207       return NULL;
1208     }
1209   
1210   if (!_dbus_string_append (&address, "tcp:"))
1211     goto error;
1212
1213   if (host != NULL && 
1214        (!_dbus_string_append (&address, "host=") ||
1215         !_dbus_string_append (&address, host)))
1216     goto error;
1217
1218   if (!_dbus_string_append (&address, ",port=") ||
1219       !_dbus_string_append_int (&address, port))
1220     goto error;
1221
1222   fd = _dbus_connect_tcp_socket (host, port, error);
1223   if (fd < 0)
1224     {
1225       _DBUS_ASSERT_ERROR_IS_SET (error);
1226       _dbus_string_free (&address);
1227       return NULL;
1228     }
1229
1230   _dbus_fd_set_close_on_exec (fd);
1231   
1232   _dbus_verbose ("Successfully connected to tcp socket %s:%d\n",
1233                  host, port);
1234   
1235   transport = _dbus_transport_new_for_socket (fd, NULL, &address);
1236   if (transport == NULL)
1237     {
1238       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1239       _dbus_close_socket (fd, NULL);
1240       _dbus_string_free (&address);
1241       fd = -1;
1242     }
1243
1244   _dbus_string_free (&address);
1245   
1246   return transport;
1247
1248 error:
1249   _dbus_string_free (&address);
1250   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1251   return NULL;
1252 }
1253
1254 /** @} */
1255