* dbus-transport-socket.c (exchange_credentials):
[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   DBusError error;
342
343   _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
344                   do_reading, do_writing);
345
346   dbus_error_init (&error);
347   if (do_writing && transport->send_credentials_pending)
348     {
349       if (_dbus_send_credentials_unix_socket (socket_transport->fd,
350                                               &error))
351         {
352           transport->send_credentials_pending = FALSE;
353         }
354       else
355         {
356           _dbus_verbose ("Failed to write credentials: %s\n", error.message);
357           dbus_error_free (&error);
358           do_io_error (transport);
359         }
360     }
361   
362   if (do_reading && transport->receive_credentials_pending)
363     {
364       if (_dbus_read_credentials_unix_socket (socket_transport->fd,
365                                               &transport->credentials,
366                                               &error))
367         {
368           transport->receive_credentials_pending = FALSE;
369         }
370       else
371         {
372           _dbus_verbose ("Failed to read credentials %s\n", error.message);
373           dbus_error_free (&error);
374           do_io_error (transport);
375         }
376     }
377
378   if (!(transport->send_credentials_pending ||
379         transport->receive_credentials_pending))
380     {
381       _dbus_auth_set_credentials (transport->auth,
382                                   &transport->credentials);
383     }
384 }
385
386 static dbus_bool_t
387 do_authentication (DBusTransport *transport,
388                    dbus_bool_t    do_reading,
389                    dbus_bool_t    do_writing,
390                    dbus_bool_t   *auth_completed)
391 {
392   dbus_bool_t oom;
393   dbus_bool_t orig_auth_state;
394
395   oom = FALSE;
396   
397   orig_auth_state = _dbus_transport_get_is_authenticated (transport);
398
399   /* This is essential to avoid the check_write_watch() at the end,
400    * we don't want to add a write watch in do_iteration before
401    * we try writing and get EAGAIN
402    */
403   if (orig_auth_state)
404     {
405       if (auth_completed)
406         *auth_completed = FALSE;
407       return TRUE;
408     }
409   
410   _dbus_transport_ref (transport);
411   
412   while (!_dbus_transport_get_is_authenticated (transport) &&
413          _dbus_transport_get_is_connected (transport))
414     {      
415       exchange_credentials (transport, do_reading, do_writing);
416       
417       if (transport->send_credentials_pending ||
418           transport->receive_credentials_pending)
419         {
420           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
421                          transport->send_credentials_pending,
422                          transport->receive_credentials_pending);
423           goto out;
424         }
425
426 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
427       switch (_dbus_auth_do_work (transport->auth))
428         {
429         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
430           _dbus_verbose (" %s auth state: waiting for input\n",
431                          TRANSPORT_SIDE (transport));
432           if (!do_reading || !read_data_into_auth (transport, &oom))
433             goto out;
434           break;
435       
436         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
437           _dbus_verbose (" %s auth state: waiting for memory\n",
438                          TRANSPORT_SIDE (transport));
439           oom = TRUE;
440           goto out;
441           break;
442       
443         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
444           _dbus_verbose (" %s auth state: bytes to send\n",
445                          TRANSPORT_SIDE (transport));
446           if (!do_writing || !write_data_from_auth (transport))
447             goto out;
448           break;
449       
450         case DBUS_AUTH_STATE_NEED_DISCONNECT:
451           _dbus_verbose (" %s auth state: need to disconnect\n",
452                          TRANSPORT_SIDE (transport));
453           do_io_error (transport);
454           break;
455       
456         case DBUS_AUTH_STATE_AUTHENTICATED:
457           _dbus_verbose (" %s auth state: authenticated\n",
458                          TRANSPORT_SIDE (transport));
459           break;
460         }
461     }
462
463  out:
464   if (auth_completed)
465     *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
466   
467   check_read_watch (transport);
468   check_write_watch (transport);
469   _dbus_transport_unref (transport);
470
471   if (oom)
472     return FALSE;
473   else
474     return TRUE;
475 }
476
477 /* returns false on oom */
478 static dbus_bool_t
479 do_writing (DBusTransport *transport)
480 {
481   int total;
482   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
483   dbus_bool_t oom;
484   
485   /* No messages without authentication! */
486   if (!_dbus_transport_get_is_authenticated (transport))
487     {
488       _dbus_verbose ("Not authenticated, not writing anything\n");
489       return TRUE;
490     }
491
492   if (transport->disconnected)
493     {
494       _dbus_verbose ("Not connected, not writing anything\n");
495       return TRUE;
496     }
497
498 #if 1
499   _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
500                  _dbus_connection_has_messages_to_send_unlocked (transport->connection),
501                  socket_transport->fd);
502 #endif
503   
504   oom = FALSE;
505   total = 0;
506
507   while (!transport->disconnected &&
508          _dbus_connection_has_messages_to_send_unlocked (transport->connection))
509     {
510       int bytes_written;
511       DBusMessage *message;
512       const DBusString *header;
513       const DBusString *body;
514       int header_len, body_len;
515       int total_bytes_to_write;
516       
517       if (total > socket_transport->max_bytes_written_per_iteration)
518         {
519           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
520                          total, socket_transport->max_bytes_written_per_iteration);
521           goto out;
522         }
523       
524       message = _dbus_connection_get_message_to_send (transport->connection);
525       _dbus_assert (message != NULL);
526       _dbus_message_lock (message);
527
528 #if 0
529       _dbus_verbose ("writing message %p\n", message);
530 #endif
531       
532       _dbus_message_get_network_data (message,
533                                       &header, &body);
534
535       header_len = _dbus_string_get_length (header);
536       body_len = _dbus_string_get_length (body);
537
538       if (_dbus_auth_needs_encoding (transport->auth))
539         {
540           if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
541             {
542               if (!_dbus_auth_encode_data (transport->auth,
543                                            header, &socket_transport->encoded_outgoing))
544                 {
545                   oom = TRUE;
546                   goto out;
547                 }
548               
549               if (!_dbus_auth_encode_data (transport->auth,
550                                            body, &socket_transport->encoded_outgoing))
551                 {
552                   _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
553                   oom = TRUE;
554                   goto out;
555                 }
556             }
557           
558           total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
559
560 #if 0
561           _dbus_verbose ("encoded message is %d bytes\n",
562                          total_bytes_to_write);
563 #endif
564           
565           bytes_written =
566             _dbus_write_socket (socket_transport->fd,
567                                 &socket_transport->encoded_outgoing,
568                                 socket_transport->message_bytes_written,
569                                 total_bytes_to_write - socket_transport->message_bytes_written);
570         }
571       else
572         {
573           total_bytes_to_write = header_len + body_len;
574
575 #if 0
576           _dbus_verbose ("message is %d bytes\n",
577                          total_bytes_to_write);          
578 #endif
579           
580           if (socket_transport->message_bytes_written < header_len)
581             {
582               bytes_written =
583                 _dbus_write_socket_two (socket_transport->fd,
584                                         header,
585                                         socket_transport->message_bytes_written,
586                                         header_len - socket_transport->message_bytes_written,
587                                         body,
588                                         0, body_len);
589             }
590           else
591             {
592               bytes_written =
593                 _dbus_write_socket (socket_transport->fd,
594                                     body,
595                                     (socket_transport->message_bytes_written - header_len),
596                                     body_len -
597                                     (socket_transport->message_bytes_written - header_len));
598             }
599         }
600
601       if (bytes_written < 0)
602         {
603           /* EINTR already handled for us */
604           
605           if (errno == EAGAIN ||
606               errno == EWOULDBLOCK)
607             goto out;
608           else
609             {
610               _dbus_verbose ("Error writing to remote app: %s\n",
611                              _dbus_strerror (errno));
612               do_io_error (transport);
613               goto out;
614             }
615         }
616       else
617         {
618           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
619                          total_bytes_to_write);
620           
621           total += bytes_written;
622           socket_transport->message_bytes_written += bytes_written;
623
624           _dbus_assert (socket_transport->message_bytes_written <=
625                         total_bytes_to_write);
626           
627           if (socket_transport->message_bytes_written == total_bytes_to_write)
628             {
629               socket_transport->message_bytes_written = 0;
630               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
631
632               _dbus_connection_message_sent (transport->connection,
633                                              message);
634             }
635         }
636     }
637
638  out:
639   if (oom)
640     return FALSE;
641   else
642     return TRUE;
643 }
644
645 /* returns false on out-of-memory */
646 static dbus_bool_t
647 do_reading (DBusTransport *transport)
648 {
649   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
650   DBusString *buffer;
651   int bytes_read;
652   int total;
653   dbus_bool_t oom;
654
655   _dbus_verbose ("%s: fd = %d\n", _DBUS_FUNCTION_NAME,
656                  socket_transport->fd);
657   
658   /* No messages without authentication! */
659   if (!_dbus_transport_get_is_authenticated (transport))
660     return TRUE;
661
662   oom = FALSE;
663   
664   total = 0;
665
666  again:
667   
668   /* See if we've exceeded max messages and need to disable reading */
669   check_read_watch (transport);
670   
671   if (total > socket_transport->max_bytes_read_per_iteration)
672     {
673       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
674                      total, socket_transport->max_bytes_read_per_iteration);
675       goto out;
676     }
677
678   _dbus_assert (socket_transport->read_watch != NULL ||
679                 transport->disconnected);
680   
681   if (transport->disconnected)
682     goto out;
683
684   if (!dbus_watch_get_enabled (socket_transport->read_watch))
685     return TRUE;
686   
687   if (_dbus_auth_needs_decoding (transport->auth))
688     {
689       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
690         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
691       else
692         bytes_read = _dbus_read_socket (socket_transport->fd,
693                                         &socket_transport->encoded_incoming,
694                                         socket_transport->max_bytes_read_per_iteration);
695
696       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
697                     bytes_read);
698       
699       if (bytes_read > 0)
700         {
701           int orig_len;
702           
703           _dbus_message_loader_get_buffer (transport->loader,
704                                            &buffer);
705
706           orig_len = _dbus_string_get_length (buffer);
707           
708           if (!_dbus_auth_decode_data (transport->auth,
709                                        &socket_transport->encoded_incoming,
710                                        buffer))
711             {
712               _dbus_verbose ("Out of memory decoding incoming data\n");
713               oom = TRUE;
714               goto out;
715             }
716
717           _dbus_message_loader_return_buffer (transport->loader,
718                                               buffer,
719                                               _dbus_string_get_length (buffer) - orig_len);
720
721           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
722         }
723     }
724   else
725     {
726       _dbus_message_loader_get_buffer (transport->loader,
727                                        &buffer);
728       
729       bytes_read = _dbus_read_socket (socket_transport->fd,
730                                       buffer, socket_transport->max_bytes_read_per_iteration);
731       
732       _dbus_message_loader_return_buffer (transport->loader,
733                                           buffer,
734                                           bytes_read < 0 ? 0 : bytes_read);
735     }
736   
737   if (bytes_read < 0)
738     {
739       /* EINTR already handled for us */
740
741       if (errno == ENOMEM)
742         {
743           _dbus_verbose ("Out of memory in read()/do_reading()\n");
744           oom = TRUE;
745           goto out;
746         }
747       else if (errno == EAGAIN ||
748                errno == EWOULDBLOCK)
749         goto out;
750       else
751         {
752           _dbus_verbose ("Error reading from remote app: %s\n",
753                          _dbus_strerror (errno));
754           do_io_error (transport);
755           goto out;
756         }
757     }
758   else if (bytes_read == 0)
759     {
760       _dbus_verbose ("Disconnected from remote app\n");
761       do_io_error (transport);
762       goto out;
763     }
764   else
765     {
766       _dbus_verbose (" read %d bytes\n", bytes_read);
767       
768       total += bytes_read;      
769
770       if (!_dbus_transport_queue_messages (transport))
771         {
772           oom = TRUE;
773           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
774           goto out;
775         }
776       
777       /* Try reading more data until we get EAGAIN and return, or
778        * exceed max bytes per iteration.  If in blocking mode of
779        * course we'll block instead of returning.
780        */
781       goto again;
782     }
783
784  out:
785   if (oom)
786     return FALSE;
787   else
788     return TRUE;
789 }
790
791 static dbus_bool_t
792 socket_handle_watch (DBusTransport *transport,
793                    DBusWatch     *watch,
794                    unsigned int   flags)
795 {
796   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
797
798   _dbus_assert (watch == socket_transport->read_watch ||
799                 watch == socket_transport->write_watch);
800   _dbus_assert (watch != NULL);
801   
802   /* Disconnect in case of an error.  In case of hangup do not
803    * disconnect the transport because data can still be in the buffer
804    * and do_reading may need several iteration to read it all (because
805    * of its max_bytes_read_per_iteration limit).  The condition where
806    * flags == HANGUP (without READABLE) probably never happen in fact.
807    */
808   if ((flags & DBUS_WATCH_ERROR) ||
809       ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE)))
810     {
811       _dbus_verbose ("Hang up or error on watch\n");
812       _dbus_transport_disconnect (transport);
813       return TRUE;
814     }
815   
816   if (watch == socket_transport->read_watch &&
817       (flags & DBUS_WATCH_READABLE))
818     {
819       dbus_bool_t auth_finished;
820 #if 1
821       _dbus_verbose ("handling read watch %p flags = %x\n",
822                      watch, flags);
823 #endif
824       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
825         return FALSE;
826
827       /* We don't want to do a read immediately following
828        * a successful authentication.  This is so we
829        * have a chance to propagate the authentication
830        * state further up.  Specifically, we need to
831        * process any pending data from the auth object.
832        */
833       if (!auth_finished)
834         {
835           if (!do_reading (transport))
836             {
837               _dbus_verbose ("no memory to read\n");
838               return FALSE;
839             }
840         }
841       else
842         {
843           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
844         }
845     }
846   else if (watch == socket_transport->write_watch &&
847            (flags & DBUS_WATCH_WRITABLE))
848     {
849 #if 1
850       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
851                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
852 #endif
853       if (!do_authentication (transport, FALSE, TRUE, NULL))
854         return FALSE;
855       
856       if (!do_writing (transport))
857         {
858           _dbus_verbose ("no memory to write\n");
859           return FALSE;
860         }
861
862       /* See if we still need the write watch */
863       check_write_watch (transport);
864     }
865 #ifdef DBUS_ENABLE_VERBOSE_MODE
866   else
867     {
868       if (watch == socket_transport->read_watch)
869         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
870                        flags);
871       else if (watch == socket_transport->write_watch)
872         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
873                        flags);
874       else
875         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
876                        watch, dbus_watch_get_fd (watch));
877     }
878 #endif /* DBUS_ENABLE_VERBOSE_MODE */
879
880   return TRUE;
881 }
882
883 static void
884 socket_disconnect (DBusTransport *transport)
885 {
886   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
887
888   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
889   
890   free_watches (transport);
891   
892   _dbus_close_socket (socket_transport->fd, NULL);
893   socket_transport->fd = -1;
894 }
895
896 static dbus_bool_t
897 socket_connection_set (DBusTransport *transport)
898 {
899   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
900
901   _dbus_watch_set_handler (socket_transport->write_watch,
902                            _dbus_connection_handle_watch,
903                            transport->connection, NULL);
904
905   _dbus_watch_set_handler (socket_transport->read_watch,
906                            _dbus_connection_handle_watch,
907                            transport->connection, NULL);
908   
909   if (!_dbus_connection_add_watch_unlocked (transport->connection,
910                                             socket_transport->write_watch))
911     return FALSE;
912
913   if (!_dbus_connection_add_watch_unlocked (transport->connection,
914                                             socket_transport->read_watch))
915     {
916       _dbus_connection_remove_watch_unlocked (transport->connection,
917                                               socket_transport->write_watch);
918       return FALSE;
919     }
920
921   check_read_watch (transport);
922   check_write_watch (transport);
923
924   return TRUE;
925 }
926
927 /**
928  * @todo We need to have a way to wake up the select sleep if
929  * a new iteration request comes in with a flag (read/write) that
930  * we're not currently serving. Otherwise a call that just reads
931  * could block a write call forever (if there are no incoming
932  * messages).
933  */
934 static  void
935 socket_do_iteration (DBusTransport *transport,
936                    unsigned int   flags,
937                    int            timeout_milliseconds)
938 {
939   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
940   DBusPollFD poll_fd;
941   int poll_res;
942   int poll_timeout;
943
944   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
945                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
946                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
947                  timeout_milliseconds,
948                  socket_transport->read_watch,
949                  socket_transport->write_watch,
950                  socket_transport->fd);
951   
952   /* the passed in DO_READING/DO_WRITING flags indicate whether to
953    * read/write messages, but regardless of those we may need to block
954    * for reading/writing to do auth.  But if we do reading for auth,
955    * we don't want to read any messages yet if not given DO_READING.
956    */
957
958   poll_fd.fd = socket_transport->fd;
959   poll_fd.events = 0;
960   
961   if (_dbus_transport_get_is_authenticated (transport))
962     {
963       /* This is kind of a hack; if we have stuff to write, then try
964        * to avoid the poll. This is probably about a 5% speedup on an
965        * echo client/server.
966        *
967        * If both reading and writing were requested, we want to avoid this
968        * since it could have funky effects:
969        *   - both ends spinning waiting for the other one to read
970        *     data so they can finish writing
971        *   - prioritizing all writing ahead of reading
972        */
973       if ((flags & DBUS_ITERATION_DO_WRITING) &&
974           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
975           !transport->disconnected &&
976           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
977         {
978           do_writing (transport);
979
980           if (transport->disconnected ||
981               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
982             goto out;
983         }
984
985       /* If we get here, we decided to do the poll() after all */
986       _dbus_assert (socket_transport->read_watch);
987       if (flags & DBUS_ITERATION_DO_READING)
988         poll_fd.events |= _DBUS_POLLIN;
989
990       _dbus_assert (socket_transport->write_watch);
991       if (flags & DBUS_ITERATION_DO_WRITING)
992         poll_fd.events |= _DBUS_POLLOUT;
993     }
994   else
995     {
996       DBusAuthState auth_state;
997       
998       auth_state = _dbus_auth_do_work (transport->auth);
999
1000       if (transport->receive_credentials_pending ||
1001           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
1002         poll_fd.events |= _DBUS_POLLIN;
1003
1004       if (transport->send_credentials_pending ||
1005           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
1006         poll_fd.events |= _DBUS_POLLOUT;
1007     }
1008
1009   if (poll_fd.events)
1010     {
1011       if (flags & DBUS_ITERATION_BLOCK)
1012         poll_timeout = timeout_milliseconds;
1013       else
1014         poll_timeout = 0;
1015
1016       /* For blocking selects we drop the connection lock here
1017        * to avoid blocking out connection access during a potentially
1018        * indefinite blocking call. The io path is still protected
1019        * by the io_path_cond condvar, so we won't reenter this.
1020        */
1021       if (flags & DBUS_ITERATION_BLOCK)
1022         {
1023           _dbus_verbose ("unlock %s pre poll\n", _DBUS_FUNCTION_NAME);
1024           _dbus_connection_unlock (transport->connection);
1025         }
1026       
1027     again:
1028       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
1029
1030       if (poll_res < 0 && errno == EINTR)
1031         goto again;
1032
1033       if (flags & DBUS_ITERATION_BLOCK)
1034         {
1035           _dbus_verbose ("lock %s post poll\n", _DBUS_FUNCTION_NAME);
1036           _dbus_connection_lock (transport->connection);
1037         }
1038       
1039       if (poll_res >= 0)
1040         {
1041           if (poll_res == 0)
1042             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
1043                                   * valgrind flags it as an error. though it probably
1044                                   * is guaranteed on linux at least.
1045                                   */
1046           
1047           if (poll_fd.revents & _DBUS_POLLERR)
1048             do_io_error (transport);
1049           else
1050             {
1051               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
1052               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
1053               dbus_bool_t authentication_completed;
1054
1055               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
1056                              need_read, need_write);
1057               do_authentication (transport, need_read, need_write,
1058                                  &authentication_completed);
1059
1060               /* See comment in socket_handle_watch. */
1061               if (authentication_completed)
1062                 goto out;
1063                                  
1064               if (need_read && (flags & DBUS_ITERATION_DO_READING))
1065                 do_reading (transport);
1066               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
1067                 do_writing (transport);
1068             }
1069         }
1070       else
1071         {
1072           _dbus_verbose ("Error from _dbus_poll(): %s\n",
1073                          _dbus_strerror (errno));
1074         }
1075     }
1076
1077
1078  out:
1079   /* We need to install the write watch only if we did not
1080    * successfully write everything. Note we need to be careful that we
1081    * don't call check_write_watch *before* do_writing, since it's
1082    * inefficient to add the write watch, and we can avoid it most of
1083    * the time since we can write immediately.
1084    * 
1085    * However, we MUST always call check_write_watch(); DBusConnection code
1086    * relies on the fact that running an iteration will notice that
1087    * messages are pending.
1088    */
1089   check_write_watch (transport);
1090
1091   _dbus_verbose (" ... leaving do_iteration()\n");
1092 }
1093
1094 static void
1095 socket_live_messages_changed (DBusTransport *transport)
1096 {
1097   /* See if we should look for incoming messages again */
1098   check_read_watch (transport);
1099 }
1100
1101
1102 static dbus_bool_t
1103 socket_get_socket_fd (DBusTransport *transport,
1104                       int           *fd_p)
1105 {
1106   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1107   
1108   *fd_p = socket_transport->fd;
1109   
1110   return TRUE;
1111 }
1112
1113 static const DBusTransportVTable socket_vtable = {
1114   socket_finalize,
1115   socket_handle_watch,
1116   socket_disconnect,
1117   socket_connection_set,
1118   socket_do_iteration,
1119   socket_live_messages_changed,
1120   socket_get_socket_fd
1121 };
1122
1123 /**
1124  * Creates a new transport for the given socket file descriptor.  The file
1125  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1126  * make it so). This function is shared by various transports that
1127  * boil down to a full duplex file descriptor.
1128  *
1129  * @param fd the file descriptor.
1130  * @param server_guid non-#NULL if this transport is on the server side of a connection
1131  * @param address the transport's address
1132  * @returns the new transport, or #NULL if no memory.
1133  */
1134 DBusTransport*
1135 _dbus_transport_new_for_socket (int               fd,
1136                                 const DBusString *server_guid,
1137                                 const DBusString *address)
1138 {
1139   DBusTransportSocket *socket_transport;
1140   
1141   socket_transport = dbus_new0 (DBusTransportSocket, 1);
1142   if (socket_transport == NULL)
1143     return NULL;
1144
1145   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
1146     goto failed_0;
1147
1148   if (!_dbus_string_init (&socket_transport->encoded_incoming))
1149     goto failed_1;
1150   
1151   socket_transport->write_watch = _dbus_watch_new (fd,
1152                                                  DBUS_WATCH_WRITABLE,
1153                                                  FALSE,
1154                                                  NULL, NULL, NULL);
1155   if (socket_transport->write_watch == NULL)
1156     goto failed_2;
1157   
1158   socket_transport->read_watch = _dbus_watch_new (fd,
1159                                                 DBUS_WATCH_READABLE,
1160                                                 FALSE,
1161                                                 NULL, NULL, NULL);
1162   if (socket_transport->read_watch == NULL)
1163     goto failed_3;
1164   
1165   if (!_dbus_transport_init_base (&socket_transport->base,
1166                                   &socket_vtable,
1167                                   server_guid, address))
1168     goto failed_4;
1169   
1170   socket_transport->fd = fd;
1171   socket_transport->message_bytes_written = 0;
1172   
1173   /* These values should probably be tunable or something. */     
1174   socket_transport->max_bytes_read_per_iteration = 2048;
1175   socket_transport->max_bytes_written_per_iteration = 2048;
1176   
1177   return (DBusTransport*) socket_transport;
1178
1179  failed_4:
1180   _dbus_watch_unref (socket_transport->read_watch);
1181  failed_3:
1182   _dbus_watch_unref (socket_transport->write_watch);
1183  failed_2:
1184   _dbus_string_free (&socket_transport->encoded_incoming);
1185  failed_1:
1186   _dbus_string_free (&socket_transport->encoded_outgoing);
1187  failed_0:
1188   dbus_free (socket_transport);
1189   return NULL;
1190 }
1191
1192 /**
1193  * Creates a new transport for the given hostname and port.
1194  *
1195  * @param host the host to connect to
1196  * @param port the port to connect to
1197  * @param error location to store reason for failure.
1198  * @returns a new transport, or #NULL on failure.
1199  */
1200 DBusTransport*
1201 _dbus_transport_new_for_tcp_socket (const char     *host,
1202                                     dbus_int32_t    port,
1203                                     DBusError      *error)
1204 {
1205   int fd;
1206   DBusTransport *transport;
1207   DBusString address;
1208   
1209   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1210
1211   if (!_dbus_string_init (&address))
1212     {
1213       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1214       return NULL;
1215     }
1216   
1217   if (!_dbus_string_append (&address, "tcp:"))
1218     goto error;
1219
1220   if (host != NULL && 
1221        (!_dbus_string_append (&address, "host=") ||
1222         !_dbus_string_append (&address, host)))
1223     goto error;
1224
1225   if (!_dbus_string_append (&address, ",port=") ||
1226       !_dbus_string_append_int (&address, port))
1227     goto error;
1228
1229   fd = _dbus_connect_tcp_socket (host, port, error);
1230   if (fd < 0)
1231     {
1232       _DBUS_ASSERT_ERROR_IS_SET (error);
1233       _dbus_string_free (&address);
1234       return NULL;
1235     }
1236
1237   _dbus_fd_set_close_on_exec (fd);
1238   
1239   _dbus_verbose ("Successfully connected to tcp socket %s:%d\n",
1240                  host, port);
1241   
1242   transport = _dbus_transport_new_for_socket (fd, NULL, &address);
1243   if (transport == NULL)
1244     {
1245       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1246       _dbus_close_socket (fd, NULL);
1247       _dbus_string_free (&address);
1248       fd = -1;
1249     }
1250
1251   _dbus_string_free (&address);
1252   
1253   return transport;
1254
1255 error:
1256   _dbus_string_free (&address);
1257   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1258   return NULL;
1259 }
1260
1261 DBusTransportOpenResult
1262 _dbus_transport_open_socket(DBusAddressEntry  *entry,
1263                             DBusTransport    **transport_p,                            
1264                             DBusError         *error)
1265 {
1266   const char *method;
1267   
1268   method = dbus_address_entry_get_method (entry);
1269   _dbus_assert (method != NULL);
1270
1271   if (strcmp (method, "tcp") == 0)
1272     {
1273       const char *host = dbus_address_entry_get_value (entry, "host");
1274       const char *port = dbus_address_entry_get_value (entry, "port");
1275       DBusString  str;
1276       long lport;
1277       dbus_bool_t sresult;
1278           
1279       if (port == NULL)
1280         {
1281           _dbus_set_bad_address (error, "tcp", "port", NULL);
1282           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1283         }
1284
1285       _dbus_string_init_const (&str, port);
1286       sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
1287       _dbus_string_free (&str);
1288           
1289       if (sresult == FALSE || lport <= 0 || lport > 65535)
1290         {
1291           _dbus_set_bad_address (error, NULL, NULL,
1292                                  "Port is not an integer between 0 and 65535");
1293           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1294         }
1295           
1296       *transport_p = _dbus_transport_new_for_tcp_socket (host, lport, error);
1297       if (*transport_p == NULL)
1298         {
1299           _DBUS_ASSERT_ERROR_IS_SET (error);
1300           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
1301         }
1302       else
1303         {
1304           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1305           return DBUS_TRANSPORT_OPEN_OK;
1306         }
1307     }
1308   else
1309     {
1310       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1311       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
1312     }
1313 }
1314
1315 /** @} */
1316