Merge branch 'master' of kenny.imendio.com:/var/git/public/projects/loudmouth into...
[jelmer/loudmouth.git] / loudmouth / lm-connection.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2003-2006 Imendio AB
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include <string.h>
24 #include <sys/stat.h> 
25 #include <sys/types.h>
26 #include <fcntl.h>
27
28 #include <glib.h>
29
30 #include "lm-sock.h"
31 #include "lm-debug.h"
32 #include "lm-error.h"
33 #include "lm-internals.h"
34 #include "lm-ssl-internals.h"
35 #include "lm-parser.h"
36 #include "lm-sha.h"
37 #include "lm-connection.h"
38 #include "lm-utils.h"
39
40 #define IN_BUFFER_SIZE 1024
41
42 typedef struct {
43         LmHandlerPriority  priority;
44         LmMessageHandler  *handler;
45 } HandlerData;
46
47 typedef struct {
48         GSource       source;
49         LmConnection *connection;
50 } LmIncomingSource;
51
52 struct _LmConnection {
53         /* Parameters */
54         GMainContext *context;
55         gchar        *server;
56         gchar        *jid;
57         guint         port;
58
59         LmSSL        *ssl;
60
61         LmProxy      *proxy;
62         
63         LmParser     *parser;
64         gchar        *stream_id;
65
66         GHashTable   *id_handlers;
67         GSList       *handlers[LM_MESSAGE_TYPE_UNKNOWN];
68
69         /* Communication */
70         GIOChannel   *io_channel;
71         guint         io_watch_in;
72         guint         io_watch_err;
73         guint         io_watch_hup;
74         LmSocket      fd;
75         guint         io_watch_connect;
76         
77         guint         open_id;
78         LmCallback   *open_cb;
79
80         gboolean      async_connect_waiting;
81         gboolean      blocking;
82
83         gboolean      cancel_open;
84         LmCallback   *close_cb;     /* unused */
85         LmCallback   *auth_cb;
86         LmCallback   *register_cb;  /* unused */
87
88         LmCallback   *disconnect_cb;
89
90         GQueue       *incoming_messages;
91         GSource      *incoming_source;
92
93         LmConnectionState state;
94
95         guint         keep_alive_rate;
96         guint         keep_alive_id;
97
98         guint         io_watch_out;
99         GString      *out_buf;
100
101         LmConnectData *connect_data;
102
103         gint          ref_count;
104 };
105
106 typedef enum {
107         AUTH_TYPE_PLAIN  = 1,
108         AUTH_TYPE_DIGEST = 2,
109         AUTH_TYPE_0K     = 4
110 } AuthType;
111
112 static void     connection_free (LmConnection *connection);
113
114
115 static void     connection_handle_message    (LmConnection         *connection,
116                                               LmMessage            *message);
117
118 static void     connection_new_message_cb    (LmParser             *parser,
119                                               LmMessage            *message,
120                                               LmConnection         *connection);
121 static gboolean connection_do_open           (LmConnection         *connection,
122                                               GError              **error);
123
124 static void     connection_do_close           (LmConnection        *connection);
125 static gint     connection_do_write          (LmConnection         *connection,
126                                               const gchar          *buf,
127                                               gint                  len);
128
129 static gboolean connection_in_event          (GIOChannel   *source,
130                                               GIOCondition  condition,
131                                               LmConnection *connection);
132 static gboolean connection_error_event       (GIOChannel   *source,
133                                               GIOCondition  condition,
134                                               LmConnection *connection);
135 static gboolean connection_hup_event         (GIOChannel   *source,
136                                               GIOCondition  condition,
137                                               LmConnection *connection);
138 static gboolean connection_send              (LmConnection         *connection,
139                                               const gchar          *str,
140                                               gint                  len,
141                                               GError               **error);
142 static LmMessage *     connection_create_auth_req_msg (const gchar *username);
143 static LmMessage *     connection_create_auth_msg     (LmConnection *connection,
144                                                        const gchar  *username,
145                                                        const gchar  *password,
146                                                        const gchar  *resource,
147                                                        gint          auth_type);
148 static LmHandlerResult connection_auth_req_reply (LmMessageHandler *handler,
149                                                   LmConnection     *connection,
150                                                   LmMessage        *m,
151                                                   gpointer          user_data);
152 static int connection_check_auth_type   (LmMessage           *auth_req_rpl);
153                                               
154 static LmHandlerResult connection_auth_reply (LmMessageHandler    *handler,
155                                               LmConnection        *connection,
156                                               LmMessage           *m,
157                                               gpointer             user_data);
158
159 static void     connection_stream_received   (LmConnection        *connection, 
160                                               LmMessage           *m);
161
162 static gint     connection_handler_compare_func (HandlerData  *a,
163                                                  HandlerData  *b);
164 static gboolean connection_incoming_prepare  (GSource         *source,
165                                               gint            *timeout);
166 static gboolean connection_incoming_check    (GSource         *source);
167 static gboolean connection_incoming_dispatch (GSource         *source,
168                                               GSourceFunc      callback,
169                                               gpointer           user_data);
170 static GSource * connection_create_source       (LmConnection *connection);
171 static void      connection_signal_disconnect   (LmConnection *connection,
172                                                  LmDisconnectReason reason);
173
174 static void     connection_do_connect           (LmConnectData *connect_data);
175 static guint    connection_add_watch            (LmConnection  *connection,
176                                                  GIOChannel    *channel,
177                                                  GIOCondition   condition,
178                                                  GIOFunc        func,
179                                                  gpointer       user_data);
180 static gboolean connection_send_keep_alive      (LmConnection  *connection);
181 static void     connection_start_keep_alive     (LmConnection  *connection);
182 static void     connection_stop_keep_alive      (LmConnection  *connection);
183 static gboolean connection_buffered_write_cb    (GIOChannel    *source, 
184                                                  GIOCondition   condition,
185                                                  LmConnection  *connection);
186 static gboolean connection_output_is_buffered   (LmConnection  *connection,
187                                                  const gchar   *buffer,
188                                                  gint           len);
189 static void     connection_setup_output_buffer  (LmConnection  *connection,
190                                                  const gchar   *buffer,
191                                                  gint           len);
192
193 static GSourceFuncs incoming_funcs = {
194         connection_incoming_prepare,
195         connection_incoming_check,
196         connection_incoming_dispatch,
197         NULL
198 };
199
200 static void
201 connection_free (LmConnection *connection)
202 {
203         int        i;
204         LmMessage *m;
205
206         g_free (connection->server);
207         g_free (connection->jid);
208         g_free (connection->stream_id);
209
210         if (connection->parser) {
211                 lm_parser_free (connection->parser);
212         }
213
214         /* Unref handlers */
215         for (i = 0; i < LM_MESSAGE_TYPE_UNKNOWN; ++i) {
216                 GSList *l;
217
218                 for (l = connection->handlers[i]; l; l = l->next) {
219                         HandlerData *hd = (HandlerData *) l->data;
220                         
221                         lm_message_handler_unref (hd->handler);
222                         g_free (hd);
223                 }
224
225                 g_slist_free (connection->handlers[i]);
226         }
227
228         g_hash_table_destroy (connection->id_handlers);
229         if (connection->state >= LM_CONNECTION_STATE_OPENING) {
230                 connection_do_close (connection);
231         }
232
233         if (connection->open_cb) {
234                 _lm_utils_free_callback (connection->open_cb);
235         }
236         
237         if (connection->auth_cb) {
238                 _lm_utils_free_callback (connection->auth_cb);
239         }
240
241         lm_connection_set_disconnect_function (connection, NULL, NULL, NULL);
242
243         while ((m = g_queue_pop_head (connection->incoming_messages)) != NULL) {
244                 lm_message_unref (m);
245         }
246
247         if (connection->ssl) {
248                 lm_ssl_unref (connection->ssl);
249         }
250
251         if (connection->proxy) {
252                 lm_proxy_unref (connection->proxy);
253         }
254
255         g_queue_free (connection->incoming_messages);
256         
257         if (connection->context) {
258                 g_main_context_unref (connection->context);
259         }
260
261         if (connection->out_buf) {
262                 g_string_free (connection->out_buf, TRUE);
263         }
264         
265         g_free (connection);
266 }
267
268 static void
269 connection_handle_message (LmConnection *connection, LmMessage *m)
270 {
271         LmMessageHandler *handler;
272         GSList           *l;
273         const gchar      *id;
274         LmHandlerResult   result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
275
276         lm_connection_ref (connection);
277
278         if (lm_message_get_type (m) == LM_MESSAGE_TYPE_STREAM) {
279                 connection_stream_received (connection, m);
280                 goto out;
281         }
282         
283         id = lm_message_node_get_attribute (m->node, "id");
284         
285         if (id) {
286                 handler = g_hash_table_lookup (connection->id_handlers, id);
287                 if (handler) {
288                         result = _lm_message_handler_handle_message (handler, 
289                                                                      connection,
290                                                                      m);
291                         g_hash_table_remove (connection->id_handlers, id);
292                 }
293         }
294         
295         if (result == LM_HANDLER_RESULT_REMOVE_MESSAGE) {
296                 goto out;
297         }
298
299         for (l = connection->handlers[lm_message_get_type (m)]; 
300              l && result == LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; 
301              l = l->next) {
302                 HandlerData *hd = (HandlerData *) l->data;
303                 
304                 result = _lm_message_handler_handle_message (hd->handler,
305                                                              connection,
306                                                              m);
307         }
308
309 out:
310         lm_connection_unref (connection);
311         
312         return;
313 }
314
315 static void
316 connection_new_message_cb (LmParser     *parser,
317                            LmMessage    *m,
318                            LmConnection *connection)
319 {
320         const gchar *from;
321         
322         lm_message_ref (m);
323
324         from = lm_message_node_get_attribute (m->node, "from");
325         if (!from) {
326                 from = "unknown";
327         }
328         
329         lm_verbose ("New message with type=\"%s\" from: %s\n",
330                     _lm_message_type_to_string (lm_message_get_type (m)),
331                     from);
332
333         g_queue_push_tail (connection->incoming_messages, m);
334 }
335
336 void
337 _lm_connection_succeeded (LmConnectData *connect_data)
338 {
339         LmConnection *connection;
340         LmMessage    *m;
341         gchar        *server_from_jid;
342         gchar        *ch;
343
344         connection = connect_data->connection;
345         
346         if (connection->io_watch_connect != 0) {
347                 GSource *source;
348
349                 source = g_main_context_find_source_by_id (connection->context,
350                                                            connection->io_watch_connect);
351                 if (source) {
352                         g_source_destroy (source);
353                 }
354                 connection->io_watch_connect = 0;
355         }
356
357         /* Need some way to report error/success */
358         if (connection->cancel_open) {
359                 lm_verbose ("Cancelling connection...\n");
360                 return;
361         }
362         
363         connection->fd = connect_data->fd;
364         connection->io_channel = connect_data->io_channel;
365
366         freeaddrinfo (connect_data->resolved_addrs);
367         connection->connect_data = NULL;
368         g_free (connect_data);
369
370         if (connection->ssl) {
371                 GError *error = NULL;
372
373                 lm_verbose ("Setting up SSL...\n");
374         
375 #ifdef HAVE_GNUTLS
376                 /* GNU TLS requires the socket to be blocking */
377                 _lm_sock_set_blocking (connection->fd, TRUE);
378 #endif
379
380                 if (!_lm_ssl_begin (connection->ssl, connection->fd,
381                                     connection->server,
382                                     &error)) {
383                         lm_verbose ("Could not begin SSL\n");
384                                     
385                         if (error) {
386                                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
387                                        "%s\n", error->message);
388                                 g_error_free (error);
389                         }
390
391                         _lm_sock_shutdown (connection->fd);
392                         _lm_sock_close (connection->fd);
393
394                         connection_do_close (connection);
395
396                         return;
397                 }
398         
399 #ifdef HAVE_GNUTLS
400                 _lm_sock_set_blocking (connection->fd, FALSE); 
401 #endif
402         }
403
404         connection->io_watch_in = 
405                 connection_add_watch (connection,
406                                       connection->io_channel,
407                                       G_IO_IN,
408                                       (GIOFunc) connection_in_event,
409                                       connection);
410
411         /* FIXME: if we add these, we don't get ANY
412          * response from the server, this is to do with the way that
413          * windows handles watches, see bug #331214.
414          */
415 #ifndef G_OS_WIN32
416                 connection->io_watch_err =
417                         connection_add_watch (connection,
418                                               connection->io_channel,
419                                               G_IO_ERR,
420                                               (GIOFunc) connection_error_event,
421                                               connection);
422                 
423                 connection->io_watch_hup =
424                         connection_add_watch (connection,
425                                               connection->io_channel,
426                                               G_IO_HUP,
427                                               (GIOFunc) connection_hup_event,
428                                               connection);
429 #endif
430
431         /* FIXME: Set up according to XMPP 1.0 specification */
432         /*        StartTLS and the like */
433         if (!connection_send (connection, 
434                               "<?xml version='1.0' encoding='UTF-8'?>", -1,
435                               NULL)) {
436                 lm_verbose ("Failed to send xml version and encoding\n");
437                 connection_do_close (connection);
438
439                 return;
440         }
441
442         if (connection->jid != NULL && (ch = strchr (connection->jid, '@')) != NULL) {
443                 server_from_jid = ch + 1;
444         } else {
445                 server_from_jid = connection->server;
446         }
447
448         m = lm_message_new (server_from_jid, LM_MESSAGE_TYPE_STREAM);
449         lm_message_node_set_attributes (m->node,
450                                         "xmlns:stream", 
451                                         "http://etherx.jabber.org/streams",
452                                         "xmlns", "jabber:client",
453                                         NULL);
454         
455         lm_verbose ("Opening stream...");
456
457         if (!lm_connection_send (connection, m, NULL)) {
458                 lm_verbose ("Failed to send stream information\n");
459                 connection_do_close (connection);
460         }
461                 
462         lm_message_unref (m);
463 }
464
465 void 
466 _lm_connection_failed_with_error (LmConnectData *connect_data, int error) 
467 {
468         LmConnection *connection;
469         
470         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
471                "Connection failed: %s (error %d)\n",
472                _lm_sock_get_error_str (error), error);
473         
474         connection = connect_data->connection;
475         
476         connect_data->current_addr = connect_data->current_addr->ai_next;
477         
478         if (connection->io_watch_connect != 0) {
479                 GSource *source;
480
481                 source = g_main_context_find_source_by_id (connection->context,
482                                                            connection->io_watch_connect);
483                 if (source) {
484                         g_source_destroy (source);
485                 }
486
487                 connection->io_watch_connect = 0;
488         }
489
490         if (connect_data->io_channel != NULL) {
491                 g_io_channel_unref (connect_data->io_channel);
492                 /* FIXME: need to check for last unref and close the socket */
493         }
494         
495         if (connect_data->current_addr == NULL) {
496                 connection_do_close (connection);
497                 if (connection->open_cb) {
498                         LmCallback *cb = connection->open_cb;
499
500                         connection->open_cb = NULL;
501                         
502                         (* ((LmResultFunction) cb->func)) (connection, FALSE,
503                                                            cb->user_data);
504                         _lm_utils_free_callback (cb);
505                 }
506                 
507                 freeaddrinfo (connect_data->resolved_addrs);
508                 connection->connect_data = NULL;
509                 g_free (connect_data);
510         } else {
511                 /* try to connect to the next host */
512                 connection_do_connect (connect_data);
513         }
514 }
515
516 void 
517 _lm_connection_failed (LmConnectData *connect_data)
518 {
519         _lm_connection_failed_with_error (connect_data, 
520                                           _lm_sock_get_last_error());
521 }
522
523 static gboolean 
524 connection_connect_cb (GIOChannel   *source, 
525                        GIOCondition  condition,
526                        LmConnectData *connect_data) 
527 {
528         LmConnection    *connection;
529         struct addrinfo *addr;
530         int              err;
531         socklen_t        len;
532         LmSocket         fd; 
533
534         connection = connect_data->connection;
535         addr = connect_data->current_addr;
536         fd = g_io_channel_unix_get_fd (source);
537         
538         if (condition == G_IO_ERR) {
539                 len = sizeof (err);
540                 _lm_sock_get_error (fd, &err, &len);
541                 if (!_lm_sock_is_blocking_error (err)) {
542                         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
543                                "Connection failed.\n");
544
545                         _lm_connection_failed_with_error (connect_data, err);
546
547                         connection->io_watch_connect = 0;
548                         return FALSE;
549                 }
550         }
551
552         if (connection->async_connect_waiting) {
553                 gint res;
554
555                 fd = g_io_channel_unix_get_fd (source);
556
557                 res = _lm_sock_connect (fd, addr->ai_addr, (int)addr->ai_addrlen);  
558                 if (res < 0) {
559                         err = _lm_sock_get_last_error ();
560                         if (_lm_sock_is_blocking_success (err)) {
561                                 connection->async_connect_waiting = FALSE;
562
563                                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
564                                        "Connection success.\n");
565                                 
566                                 _lm_connection_succeeded (connect_data);
567                         }
568                         
569                         if (connection->async_connect_waiting && 
570                             !_lm_sock_is_blocking_error (err)) {
571                                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
572                                        "Connection failed.\n");
573
574                                 _lm_sock_close (connect_data->fd);
575                                 _lm_connection_failed_with_error (connect_data, err);
576
577                                 connection->io_watch_connect = 0;
578                                 return FALSE;
579                         }
580                 } 
581         } else {                
582                 /* for blocking sockets, G_IO_OUT means we are connected */
583                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
584                        "Connection success.\n");
585                 
586                 _lm_connection_succeeded (connect_data);
587         }
588
589         return TRUE; 
590 }
591
592 static const char *
593 connection_condition_to_str (GIOCondition condition)
594 {
595         static char buf[256];
596
597         buf[0] = '\0';
598
599         if(condition & G_IO_ERR)
600                 strcat(buf, "G_IO_ERR ");
601         if(condition & G_IO_HUP)
602                 strcat(buf, "G_IO_HUP ");
603         if(condition & G_IO_NVAL)
604                 strcat(buf, "G_IO_NVAL ");
605         if(condition & G_IO_IN)
606                 strcat(buf, "G_IO_IN ");
607         if(condition & G_IO_OUT)
608                 strcat(buf, "G_IO_OUT ");
609
610         return buf;
611 }
612
613 static void
614 connection_do_connect (LmConnectData *connect_data) 
615 {
616         LmConnection    *connection;
617         LmSocket         fd;
618         int              res, err;
619         int              port;
620         char             name[NI_MAXHOST];
621         char             portname[NI_MAXSERV];
622         struct addrinfo *addr;
623         
624         connection = connect_data->connection;
625         addr = connect_data->current_addr;
626  
627         if (connection->proxy) {
628                 port = htons (lm_proxy_get_port (connection->proxy));
629         } else {
630                 port = htons (connection->port);
631         }
632         
633         ((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
634
635         res = getnameinfo (addr->ai_addr,
636                            (socklen_t)addr->ai_addrlen,
637                            name,     sizeof (name),
638                            portname, sizeof (portname),
639                            NI_NUMERICHOST | NI_NUMERICSERV);
640         
641         if (res < 0) {
642                 _lm_connection_failed (connect_data);
643                 return;
644         }
645
646         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
647                "Trying %s port %s...\n", name, portname);
648         
649         fd = _lm_sock_makesocket (addr->ai_family,
650                                   addr->ai_socktype, 
651                                   addr->ai_protocol);
652         
653         if (!_LM_SOCK_VALID (fd)) {
654                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
655                        "Failed making socket, error:%d...\n",
656                        _lm_sock_get_last_error ());
657
658                 _lm_connection_failed (connect_data);
659
660                 return;
661         }
662
663         /* Even though it says _unix_new(), it is supported by glib on
664          * win32 because glib does some cool stuff to find out if it
665          * can treat it as a FD or a windows SOCKET.
666          */
667         connect_data->fd = fd;
668         connect_data->io_channel = g_io_channel_unix_new (fd);
669         
670         g_io_channel_set_encoding (connect_data->io_channel, NULL, NULL);
671         g_io_channel_set_buffered (connect_data->io_channel, FALSE);
672
673         _lm_sock_set_blocking (connect_data->fd, 
674                                connection->blocking);
675         
676         if (connection->proxy) {
677                 connection->io_watch_connect =
678                 connection_add_watch (connection,
679                                       connect_data->io_channel,
680                                       G_IO_OUT|G_IO_ERR,
681                                       (GIOFunc) _lm_proxy_connect_cb, 
682                                       connect_data);
683         } else {
684                 connection->io_watch_connect =
685                 connection_add_watch (connection,
686                                       connect_data->io_channel,
687                                       G_IO_OUT|G_IO_ERR,
688                                       (GIOFunc) connection_connect_cb,
689                                       connect_data);
690         }
691
692         connection->async_connect_waiting = !connection->blocking;
693
694         res = _lm_sock_connect (connect_data->fd, 
695                                 addr->ai_addr, (int)addr->ai_addrlen);  
696         if (res < 0) {
697                 err = _lm_sock_get_last_error ();
698                 if (!_lm_sock_is_blocking_error (err)) {
699                         _lm_sock_close (connect_data->fd);
700                         _lm_connection_failed_with_error (connect_data, err);
701
702                         return;
703                 }
704         }
705 }
706
707 static guint
708 connection_add_watch (LmConnection *connection,
709                       GIOChannel   *channel,
710                       GIOCondition  condition,
711                       GIOFunc       func,
712                       gpointer      user_data)
713 {
714         GSource *source;
715         guint    id;
716                                                                                 
717         g_return_val_if_fail (channel != NULL, 0);
718                                                                                 
719         source = g_io_create_watch (channel, condition);
720                                                                                 
721         g_source_set_callback (source, (GSourceFunc)func, user_data, NULL);
722                                                                                 
723         id = g_source_attach (source, connection->context);
724
725         g_source_unref (source);
726   
727         return id;
728 }
729
730 static gboolean
731 connection_send_keep_alive (LmConnection *connection)
732
733         if (!connection_send (connection, " ", -1, NULL)) {
734                 lm_verbose ("Error while sending keep alive package!\n");
735         }
736
737         return TRUE;
738 }
739
740 static void
741 connection_start_keep_alive (LmConnection *connection)
742 {
743         if (connection->keep_alive_id != 0) {
744                 connection_stop_keep_alive (connection);
745         }
746
747         if (connection->keep_alive_rate > 0) {
748                 connection->keep_alive_id =
749                         g_timeout_add (connection->keep_alive_rate,
750                                        (GSourceFunc) connection_send_keep_alive,
751                                        connection);
752         }
753 }
754
755 static void
756 connection_stop_keep_alive (LmConnection *connection)
757 {
758         if (connection->keep_alive_id != 0) {
759                 g_source_remove (connection->keep_alive_id);
760         }
761
762         connection->keep_alive_id = 0;
763 }
764
765 static gboolean
766 connection_buffered_write_cb (GIOChannel   *source, 
767                               GIOCondition  condition,
768                               LmConnection *connection)
769 {
770         gint     b_written;
771         GString *out_buf;
772         /* FIXME: Do the writing */
773
774         out_buf = connection->out_buf;
775         if (!out_buf) {
776                 /* Should not be possible */
777                 return FALSE;
778         }
779
780         b_written = connection_do_write (connection, out_buf->str, out_buf->len);
781
782         if (b_written < 0) {
783                 connection_error_event (connection->io_channel, 
784                                         G_IO_HUP,
785                                         connection);
786                 return FALSE;
787         }
788
789         g_string_erase (out_buf, 0, (gsize) b_written);
790         if (out_buf->len == 0) {
791                 lm_verbose ("Output buffer is empty, going back to normal output\n");
792
793                 if (connection->io_watch_out != 0) {
794                         GSource *source;
795
796                         source = g_main_context_find_source_by_id (connection->context, 
797                                                                    connection->io_watch_out);
798                         if (source) {
799                                 g_source_destroy (source);
800                         }
801
802                         connection->io_watch_out = 0;
803                 }
804
805                 g_string_free (out_buf, TRUE);
806                 connection->out_buf = NULL;
807                 return FALSE;
808         }
809
810         return TRUE;
811 }
812
813 static gboolean
814 connection_output_is_buffered (LmConnection *connection,
815                                const gchar  *buffer,
816                                gint          len)
817 {
818         if (connection->out_buf) {
819                 lm_verbose ("Appending %d bytes to output buffer\n", len);
820                 g_string_append_len (connection->out_buf, buffer, len);
821                 return TRUE;
822         }
823
824         return FALSE;
825 }
826
827 static void
828 connection_setup_output_buffer (LmConnection *connection,
829                                 const gchar  *buffer,
830                                 gint          len)
831 {
832         lm_verbose ("OUTPUT BUFFER ENABLED\n");
833
834         connection->out_buf = g_string_new_len (buffer, len);
835
836         connection->io_watch_out =
837                 connection_add_watch (connection,
838                                       connection->io_channel,
839                                       G_IO_OUT,
840                                       (GIOFunc) connection_buffered_write_cb,
841                                       connection);
842 }
843
844 /* Returns directly */
845 /* Setups all data needed to start the connection attempts */
846 static gboolean
847 connection_do_open (LmConnection *connection, GError **error) 
848 {
849         struct addrinfo  req;
850         struct addrinfo *ans;
851         LmConnectData   *data;
852
853         if (lm_connection_is_open (connection)) {
854                 g_set_error (error,
855                              LM_ERROR,
856                              LM_ERROR_CONNECTION_NOT_OPEN,
857                              "Connection is already open, call lm_connection_close() first");
858                 return FALSE;
859         }
860
861         if (!connection->server) {
862                 g_set_error (error,
863                              LM_ERROR,
864                              LM_ERROR_CONNECTION_FAILED,
865                              "You need to set the server hostname in the call to lm_connection_new()");
866                 return FALSE;
867         }
868
869         /* source thingie for messages and stuff */
870         connection->incoming_source = connection_create_source (connection);
871         g_source_attach (connection->incoming_source, connection->context);
872         
873         lm_verbose ("Connecting to: %s:%d\n", 
874                     connection->server, connection->port);
875
876         memset (&req, 0, sizeof(req));
877
878         req.ai_family   = AF_UNSPEC;
879         req.ai_socktype = SOCK_STREAM;
880         req.ai_protocol = IPPROTO_TCP;
881         
882         connection->cancel_open = FALSE;
883         connection->state = LM_CONNECTION_STATE_OPENING;
884         connection->async_connect_waiting = FALSE;
885         
886         if (connection->proxy) {
887                 int          err;
888                 const gchar *proxy_server;
889
890                 proxy_server = lm_proxy_get_server (connection->proxy);
891
892                 /* Connect through proxy */
893                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
894                        "Going to connect to proxy %s\n", proxy_server);
895
896                 err = getaddrinfo (proxy_server, NULL, &req, &ans);
897                 if (err != 0) {
898                         const char *str;
899
900                         str = _lm_sock_addrinfo_get_error_str (err);
901                         g_set_error (error,
902                                      LM_ERROR,                 
903                                      LM_ERROR_CONNECTION_FAILED,   
904                                      str);
905                         return FALSE;
906                 }
907         } else { 
908                 int err;
909
910                 /* Connect directly */
911                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
912                        "Going to connect to %s\n", 
913                        connection->server);
914
915                 err = getaddrinfo (connection->server, 
916                                    NULL, &req, &ans);
917                 if (err != 0) {
918                         const char *str;
919
920                         str = _lm_sock_addrinfo_get_error_str (err);
921                         g_set_error (error,
922                                      LM_ERROR,                 
923                                      LM_ERROR_CONNECTION_FAILED,   
924                                      str);
925                         return FALSE;
926                 }
927         }
928
929         if (connection->ssl) {
930                 _lm_ssl_initialize (connection->ssl);
931         }
932
933         /* Prepare and do the nonblocking connection */
934         data = g_new (LmConnectData, 1);
935
936         data->connection     = connection;
937         data->resolved_addrs = ans;
938         data->current_addr   = ans;
939         data->io_channel     = NULL;
940         data->fd             = -1;
941
942         connection->connect_data = data;
943
944         connection_do_connect (data);
945         return TRUE;
946 }
947                                         
948 static void
949 connection_do_close (LmConnection *connection)
950 {
951         GSource       *source;
952         LmConnectData *data;
953
954         connection_stop_keep_alive (connection);
955
956         if (connection->io_watch_connect != 0) {
957
958                 source = g_main_context_find_source_by_id (connection->context,
959                                                            connection->io_watch_connect);
960
961                 if (source) {
962                         g_source_destroy (source);
963                 }
964
965                 connection->io_watch_connect = 0;
966         }
967         
968         data = connection->connect_data;
969         if (data) {
970                 freeaddrinfo (data->resolved_addrs);
971                 connection->connect_data = NULL;
972                 g_free (data);
973         }
974
975         if (connection->io_channel) {
976                 if (connection->io_watch_in != 0) {
977                         source = g_main_context_find_source_by_id (connection->context,
978                                                                    connection->io_watch_in);
979                         if (source) {
980                                 g_source_destroy (source);
981                         }
982                         
983                         connection->io_watch_in = 0;
984                 }
985
986                 if (connection->io_watch_err != 0) {
987                         source = g_main_context_find_source_by_id (connection->context, 
988                                                                    connection->io_watch_err);
989                         if (source) {
990                                 g_source_destroy (source);
991                         }
992
993                         connection->io_watch_err = 0;
994                 }
995
996                 if (connection->io_watch_hup != 0) {
997                         source = g_main_context_find_source_by_id (connection->context, 
998                                                                    connection->io_watch_hup);
999
1000                         if (source) {
1001                                 g_source_destroy (source);
1002                         }
1003                         
1004                         connection->io_watch_hup = 0;
1005                 }
1006
1007                 if (connection->io_watch_out != 0) {
1008                         source = g_main_context_find_source_by_id (connection->context, 
1009                                                                    connection->io_watch_out);
1010
1011                         if (source) {
1012                                 g_source_destroy (source);
1013                         }
1014
1015                         connection->io_watch_out = 0;
1016                 }
1017
1018
1019                 g_io_channel_unref (connection->io_channel);
1020                 connection->io_channel = NULL;
1021
1022                 connection->fd = -1;
1023         }
1024
1025         if (connection->incoming_source) {
1026                 g_source_destroy (connection->incoming_source);
1027                 g_source_unref (connection->incoming_source);
1028                 connection->incoming_source = NULL;
1029         }
1030
1031         if (!lm_connection_is_open (connection)) {
1032                 /* lm_connection_is_open is FALSE for state OPENING as well */
1033                 connection->state = LM_CONNECTION_STATE_CLOSED;
1034                 connection->async_connect_waiting = FALSE;
1035                 return;
1036         }
1037         
1038         connection->state = LM_CONNECTION_STATE_CLOSED;
1039         connection->async_connect_waiting = FALSE;
1040         if (connection->ssl) {
1041                 _lm_ssl_close (connection->ssl);
1042         }
1043 }
1044
1045 static gint
1046 connection_do_write (LmConnection *connection,
1047                      const gchar  *buf,
1048                      gint          len)
1049 {
1050         gint b_written;
1051
1052         if (connection->ssl) {
1053                 b_written = _lm_ssl_send (connection->ssl, buf, len);
1054         } else {
1055                 GIOStatus io_status = G_IO_STATUS_AGAIN;
1056                 gsize     bytes_written;
1057
1058                 while (io_status == G_IO_STATUS_AGAIN) {
1059                         io_status = g_io_channel_write_chars (connection->io_channel, 
1060                                                               buf, len, 
1061                                                               &bytes_written,
1062                                                               NULL);
1063                 }
1064
1065                 b_written = bytes_written;
1066
1067                 if (io_status != G_IO_STATUS_NORMAL) {
1068                         b_written = -1;
1069                 }
1070         }
1071
1072         return b_written;
1073 }
1074
1075 static gboolean
1076 connection_read_incoming (LmConnection *connection,
1077                           gchar        *buf,
1078                           gsize         buf_size,
1079                           gsize        *bytes_read,
1080                           gboolean     *hangup)
1081 {
1082         GIOStatus status;
1083
1084         *hangup = FALSE;
1085
1086         if (connection->ssl) {
1087                 status = _lm_ssl_read (connection->ssl, 
1088                                        buf, buf_size - 1, bytes_read);
1089         } else {
1090                 status = g_io_channel_read_chars (connection->io_channel,
1091                                                   buf, buf_size - 1,
1092                                                   bytes_read,
1093                                                   NULL);
1094         }
1095
1096         if (status != G_IO_STATUS_NORMAL || *bytes_read < 0) {
1097                 gint reason;
1098                 
1099                 switch (status) {
1100                 case G_IO_STATUS_EOF:
1101                         reason = LM_DISCONNECT_REASON_HUP;
1102                         break;
1103                 case G_IO_STATUS_AGAIN:
1104                         /* No data readable but we didn't hangup */
1105                         return FALSE;
1106                         break;
1107                 case G_IO_STATUS_ERROR:
1108                         reason = LM_DISCONNECT_REASON_ERROR;
1109                         break;
1110                 default:
1111                         reason = LM_DISCONNECT_REASON_UNKNOWN;
1112                 }
1113
1114                 connection_do_close (connection);
1115                 connection_signal_disconnect (connection, reason);
1116
1117                 /* Notify connection_in_event that we hangup the connection */
1118                 *hangup = TRUE;
1119                 
1120                 return FALSE;
1121         }
1122
1123         buf[*bytes_read] = '\0';
1124
1125         /* There is more data to be read */
1126         return TRUE;
1127 }
1128
1129 static gboolean
1130 connection_in_event (GIOChannel   *source,
1131                      GIOCondition  condition,
1132                      LmConnection *connection)
1133 {
1134         gchar    buf[IN_BUFFER_SIZE];
1135         gsize    bytes_read;
1136         gboolean hangup;
1137
1138         if (connection->io_channel == NULL) {
1139                 return FALSE;
1140         }
1141
1142         while (connection_read_incoming (connection, buf, IN_BUFFER_SIZE,
1143                                          &bytes_read, &hangup)) {
1144                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "\nRECV [%d]:\n", 
1145                        (int)bytes_read);
1146                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
1147                        "-----------------------------------\n");
1148                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "'%s'\n", buf);
1149                 g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
1150                        "-----------------------------------\n");
1151
1152                 lm_verbose ("Read: %d chars\n", (int)bytes_read);
1153
1154                 lm_parser_parse (connection->parser, buf);
1155         }
1156
1157         if (hangup) {
1158                 return FALSE;
1159         }
1160
1161         return TRUE;
1162 }
1163
1164 static gboolean
1165 connection_error_event (GIOChannel   *source,
1166                         GIOCondition  condition,
1167                         LmConnection *connection)
1168 {
1169         lm_verbose ("Error event: %d->'%s'\n", 
1170                     condition, connection_condition_to_str (condition));
1171
1172         if (!connection->io_channel) {
1173                 return FALSE;
1174         }
1175
1176         connection_do_close (connection);
1177         connection_signal_disconnect (connection, LM_DISCONNECT_REASON_ERROR);
1178         
1179         return TRUE;
1180 }
1181
1182 static gboolean
1183 connection_hup_event (GIOChannel   *source,
1184                       GIOCondition  condition,
1185                       LmConnection *connection)
1186 {
1187         lm_verbose ("HUP event: %d->'%s'\n", 
1188                     condition, connection_condition_to_str (condition));
1189
1190         if (!connection->io_channel) {
1191                 return FALSE;
1192         }
1193
1194         connection_do_close (connection);
1195         connection_signal_disconnect (connection, LM_DISCONNECT_REASON_HUP);
1196         
1197         return TRUE;
1198 }
1199
1200 static gboolean
1201 connection_send (LmConnection  *connection, 
1202                  const gchar   *str, 
1203                  gint           len, 
1204                  GError       **error)
1205 {
1206         gint b_written;
1207         
1208         if (connection->state < LM_CONNECTION_STATE_OPENING) {
1209                 g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
1210                        "Connection is not open.\n");
1211
1212                 g_set_error (error,
1213                              LM_ERROR,
1214                              LM_ERROR_CONNECTION_NOT_OPEN,
1215                              "Connection is not open, call lm_connection_open() first");
1216                 return FALSE;
1217         }
1218
1219         if (len == -1) {
1220                 len = strlen (str);
1221         }
1222
1223         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "\nSEND:\n");
1224         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
1225                "-----------------------------------\n");
1226         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "%s\n", str);
1227         g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
1228                "-----------------------------------\n");
1229
1230         /* Check to see if there already is an output buffer, if so, add to the
1231            buffer and return */
1232
1233         if (connection_output_is_buffered (connection, str, len)) {
1234                 return TRUE;
1235         }
1236
1237         b_written = connection_do_write (connection, str, len);
1238
1239
1240         if (b_written < 0) {
1241                 connection_error_event (connection->io_channel, 
1242                                         G_IO_HUP,
1243                                         connection);
1244                 return FALSE;
1245         }
1246
1247         if (b_written < len) {
1248                 connection_setup_output_buffer (connection, 
1249                                                 str + b_written, 
1250                                                 len - b_written);
1251         }
1252
1253         return TRUE;
1254 }
1255
1256 typedef struct {
1257         gchar        *username;
1258         gchar        *password;
1259         gchar        *resource;
1260 } AuthReqData;
1261
1262 static void 
1263 auth_req_data_free (AuthReqData *data) {
1264         g_free (data->username);
1265         g_free (data->password);
1266         g_free (data->resource);
1267         g_free (data);
1268 }
1269
1270 static LmMessage *
1271 connection_create_auth_req_msg (const gchar *username)
1272 {
1273         LmMessage     *m;
1274         LmMessageNode *q_node;
1275         
1276         m = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
1277                                           LM_MESSAGE_SUB_TYPE_GET);
1278         q_node = lm_message_node_add_child (m->node, "query", NULL);
1279         lm_message_node_set_attributes (q_node,
1280                                         "xmlns", "jabber:iq:auth",
1281                                         NULL);
1282         lm_message_node_add_child (q_node, "username", username);
1283
1284         return m;
1285 }
1286
1287 static LmMessage *
1288 connection_create_auth_msg (LmConnection *connection,
1289                             const gchar  *username,
1290                             const gchar  *password,
1291                             const gchar  *resource,
1292                             gint          auth_type)
1293 {
1294         LmMessage     *auth_msg;
1295         LmMessageNode *q_node;
1296
1297         auth_msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
1298                                                  LM_MESSAGE_SUB_TYPE_SET);
1299         
1300         q_node = lm_message_node_add_child (auth_msg->node, "query", NULL);
1301         
1302         lm_message_node_set_attributes (q_node,
1303                                         "xmlns", "jabber:iq:auth", 
1304                                         NULL);
1305
1306         lm_message_node_add_child (q_node, "username", username);
1307         
1308         if (auth_type & AUTH_TYPE_0K) {
1309                 lm_verbose ("Using 0k auth (not implemented yet)\n");
1310                 /* TODO: Should probably use this? */
1311         }
1312
1313         if (auth_type & AUTH_TYPE_DIGEST) {
1314                 gchar       *str;
1315                 const gchar *digest;
1316
1317                 lm_verbose ("Using digest\n");
1318                 str = g_strconcat (connection->stream_id, password, NULL);
1319                 digest = lm_sha_hash (str);
1320                 g_free (str);
1321                 lm_message_node_add_child (q_node, "digest", digest);
1322         } 
1323         else if (auth_type & AUTH_TYPE_PLAIN) {
1324                 lm_verbose ("Using plaintext auth\n");
1325                 lm_message_node_add_child (q_node, "password", password);
1326         } else {
1327                 /* TODO: Report error somehow */
1328         }
1329         
1330         lm_message_node_add_child (q_node, "resource", resource);
1331
1332         return auth_msg;
1333 }
1334
1335 static LmHandlerResult
1336 connection_auth_req_reply (LmMessageHandler *handler,
1337                            LmConnection     *connection,
1338                            LmMessage        *m,
1339                            gpointer          user_data)
1340 {
1341         int               auth_type;
1342         LmMessage        *auth_msg;
1343         LmMessageHandler *auth_handler;
1344         AuthReqData      *data = (AuthReqData *) user_data;      
1345         gboolean          result;
1346         
1347         auth_type = connection_check_auth_type (m);
1348
1349         auth_msg = connection_create_auth_msg (connection, 
1350                                                data->username,
1351                                                data->password,
1352                                                data->resource,
1353                                                auth_type);
1354
1355         auth_handler = lm_message_handler_new (connection_auth_reply,
1356                                                NULL, NULL);
1357         result = lm_connection_send_with_reply (connection, auth_msg, 
1358                                                 auth_handler, NULL);
1359         lm_message_handler_unref (auth_handler);
1360         lm_message_unref (auth_msg);
1361         
1362         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1363 }
1364
1365 static int
1366 connection_check_auth_type (LmMessage *auth_req_rpl)
1367 {
1368         LmMessageNode *q_node;
1369         gint           ret_val = 0; 
1370
1371         q_node = lm_message_node_get_child (auth_req_rpl->node, "query");
1372         
1373         if (!q_node) {
1374                 return AUTH_TYPE_PLAIN;
1375         }
1376
1377         if (lm_message_node_get_child (q_node, "password")) {
1378                 ret_val |= AUTH_TYPE_PLAIN;
1379         }
1380
1381         if (lm_message_node_get_child (q_node, "digest")) {
1382                 ret_val |= AUTH_TYPE_DIGEST;
1383         }
1384
1385         if (lm_message_node_get_child (q_node, "sequence") &&
1386             lm_message_node_get_child (q_node, "token")) {
1387                 ret_val |= AUTH_TYPE_0K;
1388         }
1389
1390         return ret_val;
1391 }
1392
1393 static LmHandlerResult 
1394 connection_auth_reply (LmMessageHandler *handler,
1395                        LmConnection     *connection,
1396                        LmMessage        *m,
1397                        gpointer          user_data)
1398 {
1399         const gchar *type;
1400         gboolean     result = TRUE;
1401         
1402         g_return_val_if_fail (connection != NULL, 
1403                               LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS);
1404         
1405
1406         type = lm_message_node_get_attribute (m->node, "type");
1407         if (strcmp (type, "result") == 0) {
1408                 result = TRUE;
1409                 connection->state = LM_CONNECTION_STATE_AUTHENTICATED;
1410         } 
1411         else if (strcmp (type, "error") == 0) {
1412                 result = FALSE;
1413                 connection->state = LM_CONNECTION_STATE_OPEN;
1414         }
1415         
1416         lm_verbose ("AUTH reply: %d\n", result);
1417         
1418         if (connection->auth_cb) {
1419                 LmCallback *cb = connection->auth_cb;
1420
1421                 connection->auth_cb = NULL;
1422
1423                 if (cb->func) {
1424                         (* ((LmResultFunction) cb->func)) (connection, 
1425                                                            result, cb->user_data);
1426                 }
1427
1428                 _lm_utils_free_callback (cb);
1429         }
1430         
1431         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1432 }
1433
1434
1435 static void
1436 connection_stream_received (LmConnection *connection, LmMessage *m)
1437 {
1438         gboolean result;
1439         
1440         g_return_if_fail (connection != NULL);
1441         g_return_if_fail (m != NULL);
1442         
1443         connection->stream_id = g_strdup (lm_message_node_get_attribute (m->node,
1444                                                                          "id"));;
1445         
1446         lm_verbose ("Stream received: %s\n", connection->stream_id);
1447         
1448         connection->state = LM_CONNECTION_STATE_OPEN;
1449         
1450         /* Check to see if the stream is correctly set up */
1451         result = TRUE;
1452
1453         connection_start_keep_alive (connection);
1454
1455         if (connection->open_cb) {
1456                 LmCallback *cb = connection->open_cb;
1457
1458                 connection->open_cb = NULL;
1459                 
1460                 if (cb->func) {
1461                         (* ((LmResultFunction) cb->func)) (connection, result,
1462                                                            cb->user_data);
1463
1464                 }
1465                 _lm_utils_free_callback (connection->open_cb);
1466         }
1467 }
1468
1469 static gint
1470 connection_handler_compare_func (HandlerData *a, HandlerData *b)
1471 {
1472         return b->priority - a->priority;
1473 }
1474
1475 static gboolean 
1476 connection_incoming_prepare (GSource *source, gint *timeout)
1477 {
1478         LmConnection *connection;
1479         
1480         connection = ((LmIncomingSource *)source)->connection;
1481         
1482         return !g_queue_is_empty (connection->incoming_messages);
1483 }
1484
1485 static gboolean
1486 connection_incoming_check (GSource *source)
1487 {
1488         return FALSE;
1489 }
1490
1491 static gboolean
1492 connection_incoming_dispatch (GSource *source, 
1493                               GSourceFunc callback, 
1494                               gpointer user_data)
1495 {
1496         LmConnection *connection;
1497         LmMessage    *m;
1498         
1499         connection = ((LmIncomingSource *) source)->connection;
1500
1501         m = (LmMessage *) g_queue_pop_head (connection->incoming_messages);
1502         
1503         if (m) {
1504                 connection_handle_message (connection, m);
1505                 lm_message_unref (m);
1506         }
1507
1508         return TRUE;
1509 }
1510
1511 static GSource *
1512 connection_create_source (LmConnection *connection)
1513 {
1514         GSource *source;
1515         
1516         source = g_source_new (&incoming_funcs, sizeof (LmIncomingSource));
1517         ((LmIncomingSource *) source)->connection = connection;
1518         
1519         return source;
1520 }
1521
1522 static void
1523 connection_signal_disconnect (LmConnection       *connection,
1524                               LmDisconnectReason  reason)
1525 {
1526         if (connection->disconnect_cb && connection->disconnect_cb->func) {
1527                 LmCallback *cb = connection->disconnect_cb;
1528                 
1529                 (* ((LmDisconnectFunction) cb->func)) (connection,
1530                                                        reason,
1531                                                        cb->user_data);
1532         }
1533 }
1534
1535 /**
1536  * lm_connection_new:
1537  * @server: The hostname to the server for the connection.
1538  * 
1539  * Creates a new closed connection. To open the connection call 
1540  * lm_connection_open(). @server can be #NULL but must be set before calling lm_connection_open().
1541  * 
1542  * Return value: A newly created LmConnection, should be unreffed with lm_connection_unref().
1543  **/
1544 LmConnection *
1545 lm_connection_new (const gchar *server)
1546 {
1547         LmConnection *connection;
1548         gint          i;
1549         
1550         lm_debug_init ();
1551         _lm_sock_library_init ();
1552
1553         connection = g_new0 (LmConnection, 1);
1554
1555         if (server) {
1556                 connection->server = _lm_utils_hostname_to_punycode (server);
1557         } else {
1558                 connection->server = NULL;
1559         }
1560
1561         connection->context           = NULL;
1562         connection->port              = LM_CONNECTION_DEFAULT_PORT;
1563         connection->jid               = NULL;
1564         connection->ssl               = NULL;
1565         connection->proxy             = NULL;
1566         connection->disconnect_cb     = NULL;
1567         connection->incoming_messages = g_queue_new ();
1568         connection->cancel_open       = FALSE;
1569         connection->state             = LM_CONNECTION_STATE_CLOSED;
1570         connection->keep_alive_id     = 0;
1571         connection->keep_alive_rate   = 0;
1572         connection->out_buf           = NULL;
1573         connection->connect_data      = NULL;
1574         
1575         connection->id_handlers = g_hash_table_new_full (g_str_hash, 
1576                                                          g_str_equal,
1577                                                          g_free, 
1578                                                          (GDestroyNotify) lm_message_handler_unref);
1579         connection->ref_count         = 1;
1580         
1581         for (i = 0; i < LM_MESSAGE_TYPE_UNKNOWN; ++i) {
1582                 connection->handlers[i] = NULL;
1583         }
1584
1585         connection->parser = lm_parser_new 
1586                 ((LmParserMessageFunction) connection_new_message_cb, 
1587                  connection, NULL);
1588
1589         return connection;
1590 }
1591
1592 /**
1593  * lm_connection_new_with_context:
1594  * @server: The hostname to the server for the connection.
1595  * @context: The context this connection should be running in.
1596  * 
1597  * Creates a new closed connection running in a certain context. To open the 
1598  * connection call #lm_connection_open. @server can be #NULL but must be set 
1599  * before calling #lm_connection_open.
1600  * 
1601  * Return value: A newly created LmConnection, should be unreffed with lm_connection_unref().
1602  **/
1603 LmConnection *
1604 lm_connection_new_with_context (const gchar *server, GMainContext *context)
1605 {
1606         LmConnection *connection;
1607
1608         connection = lm_connection_new (server);
1609         connection->context = context;
1610
1611         if (context) {
1612                 g_main_context_ref (connection->context);
1613         }
1614
1615         return connection;
1616 }
1617
1618 /**
1619  * lm_connection_open:
1620  * @connection: #LmConnection to open
1621  * @function: Callback function that will be called when the connection is open.
1622  * @user_data: User data that will be passed to @function.
1623  * @notify: Function for freeing that user_data, can be NULL.
1624  * @error: location to store error, or %NULL
1625  * 
1626  * An async call to open @connection. When the connection is open @function will be called.
1627  * 
1628  * Return value: #TRUE if everything went fine, otherwise #FALSE.
1629  **/
1630 gboolean
1631 lm_connection_open (LmConnection      *connection, 
1632                     LmResultFunction   function,
1633                     gpointer           user_data,
1634                     GDestroyNotify     notify,
1635                     GError           **error)
1636 {
1637         g_return_val_if_fail (connection != NULL, FALSE);
1638         
1639         connection->open_cb = _lm_utils_new_callback (function, 
1640                                                       user_data, notify);
1641         connection->blocking = FALSE;
1642
1643         return connection_do_open (connection, error);
1644 }
1645
1646 /**
1647  * lm_connection_open_and_block:
1648  * @connection: an #LmConnection to open
1649  * @error: location to store error, or %NULL
1650  * 
1651  * Opens @connection and waits until the stream is setup. 
1652  * 
1653  * Return value: #TRUE if no errors where encountered during opening and stream setup successfully, #FALSE otherwise.
1654  **/
1655 gboolean
1656 lm_connection_open_and_block (LmConnection *connection, GError **error)
1657 {
1658         gboolean          result;
1659         LmConnectionState state;
1660         
1661         g_return_val_if_fail (connection != NULL, FALSE);
1662
1663         connection->open_cb = NULL;
1664         connection->blocking = TRUE;
1665
1666         result = connection_do_open (connection, error);
1667
1668         if (result == FALSE) {
1669                 return FALSE;
1670         }
1671                 
1672         while ((state = lm_connection_get_state (connection)) == LM_CONNECTION_STATE_OPENING) {
1673                 if (g_main_context_pending (connection->context)) {
1674                         g_main_context_iteration (connection->context, TRUE);
1675                 } else {
1676                         /* Sleep for 1 millisecond */
1677                         g_usleep (1000);
1678                 }
1679         }
1680
1681         if (lm_connection_is_open (connection)) {
1682                 connection_start_keep_alive (connection);
1683                 return TRUE;
1684         }
1685
1686         /* Need to set the error here: LM-15 */
1687         g_set_error (error,
1688                      LM_ERROR,
1689                      LM_ERROR_CONNECTION_FAILED,
1690                      "Opening the connection failed");
1691
1692         return FALSE;
1693 }
1694
1695 /**
1696  * lm_connection_cancel_open:
1697  * @connection: an #LmConnection to cancel opening on
1698  *
1699  * Cancels the open operation of a connection. The connection should be in the state #LM_CONNECTION_STATE_OPENING.
1700  **/
1701 void
1702 lm_connection_cancel_open (LmConnection *connection)
1703 {
1704         g_return_if_fail (connection != NULL);
1705
1706         connection->cancel_open = TRUE;
1707 }
1708
1709 /**
1710  * lm_connection_close:
1711  * @connection: #LmConnection to close 
1712  * @error: location to store error, or %NULL
1713  * 
1714  * A synchronous call to close the connection. When returning the connection is considered to be closed and can be opened again with lm_connection_open().
1715  * 
1716  * Return value: Returns #TRUE if no errors where detected, otherwise #FALSE.
1717  **/
1718 gboolean
1719 lm_connection_close (LmConnection      *connection, 
1720                      GError           **error)
1721 {
1722         gboolean no_errors = TRUE;
1723         
1724         g_return_val_if_fail (connection != NULL, FALSE);
1725
1726         if (connection->state == LM_CONNECTION_STATE_CLOSED) {
1727                 g_set_error (error,
1728                              LM_ERROR,
1729                              LM_ERROR_CONNECTION_NOT_OPEN,
1730                              "Connection is not open, call lm_connection_open() first");
1731                 return FALSE;
1732         }
1733
1734         lm_verbose ("Disconnecting from: %s:%d\n", 
1735                     connection->server, connection->port);
1736         
1737         if (lm_connection_is_open (connection)) {
1738                 if (!connection_send (connection, "</stream:stream>", -1, error)) {
1739                         no_errors = FALSE;
1740                 }
1741                 
1742                 g_io_channel_flush (connection->io_channel, NULL);
1743         }
1744         
1745         connection_do_close (connection);
1746         connection_signal_disconnect (connection, LM_DISCONNECT_REASON_OK);
1747         
1748         return no_errors;
1749 }
1750
1751 /**
1752  * lm_connection_authenticate:
1753  * @connection: #LmConnection to authenticate.
1754  * @username: Username used to authenticate.
1755  * @password: Password corresponding to @username.
1756  * @resource: Resource used for this connection.
1757  * @function: Callback called when authentication is finished.
1758  * @user_data: Userdata passed to @function when called.
1759  * @notify: Destroy function to free the memory used by @user_data, can be NULL.
1760  * @error: location to store error, or %NULL
1761  * 
1762  * Tries to authenticate a user against the server. The #LmResult in the result callback @function will say whether it succeeded or not. 
1763  * 
1764  * Return value: #TRUE if no errors where detected while sending the authentication message, #FALSE otherwise.
1765  **/
1766 gboolean
1767 lm_connection_authenticate (LmConnection      *connection,
1768                             const gchar       *username,
1769                             const gchar       *password,
1770                             const gchar       *resource,
1771                             LmResultFunction   function,
1772                             gpointer           user_data,
1773                             GDestroyNotify     notify,
1774                             GError           **error)
1775 {
1776         LmMessage        *m;
1777         LmMessageHandler *handler;
1778         gboolean          result;
1779         AuthReqData      *data;
1780         
1781         g_return_val_if_fail (connection != NULL, FALSE);
1782         g_return_val_if_fail (username != NULL, FALSE);
1783         g_return_val_if_fail (password != NULL, FALSE);
1784         g_return_val_if_fail (resource != NULL, FALSE);
1785
1786         if (!lm_connection_is_open (connection)) {
1787                 g_set_error (error,
1788                              LM_ERROR,
1789                              LM_ERROR_CONNECTION_NOT_OPEN,
1790                              "Connection is not open, call lm_connection_open() first");
1791                 return FALSE;
1792         }
1793
1794         /* FIXME: Do SASL authentication here (if XMPP 1.0 is used) */
1795
1796         connection->state = LM_CONNECTION_STATE_AUTHENTICATING;
1797         
1798         connection->auth_cb = _lm_utils_new_callback (function, 
1799                                                       user_data, 
1800                                                       notify);
1801
1802         m = connection_create_auth_req_msg (username);
1803                 
1804         data = g_new0 (AuthReqData, 1);
1805         data->username = g_strdup (username);
1806         data->password = g_strdup (password);
1807         data->resource = g_strdup (resource);
1808         
1809         handler = lm_message_handler_new (connection_auth_req_reply, 
1810                                           data, 
1811                                           (GDestroyNotify) auth_req_data_free);
1812         result = lm_connection_send_with_reply (connection, m, handler, error);
1813         
1814         lm_message_handler_unref (handler);
1815         lm_message_unref (m);
1816
1817         return result;
1818 }
1819
1820 /**
1821  * lm_connection_authenticate_and_block:
1822  * @connection: an #LmConnection
1823  * @username: Username used to authenticate.
1824  * @password: Password corresponding to @username.
1825  * @resource: Resource used for this connection.
1826  * @error: location to store error, or %NULL
1827  * 
1828  * Tries to authenticate a user against the server. This function blocks until a reply to the authentication attempt is returned and returns whether it was successful or not.
1829  * 
1830  * Return value: #TRUE if no errors where detected and authentication was successful. #FALSE otherwise.
1831  **/
1832 gboolean
1833 lm_connection_authenticate_and_block (LmConnection  *connection,
1834                                       const gchar   *username,
1835                                       const gchar   *password,
1836                                       const gchar   *resource,
1837                                       GError       **error)
1838 {
1839         LmMessage        *m;
1840         LmMessage        *result;
1841         LmMessageSubType  type;
1842                 
1843         g_return_val_if_fail (connection != NULL, FALSE);
1844         g_return_val_if_fail (username != NULL, FALSE);
1845         g_return_val_if_fail (password != NULL, FALSE);
1846         g_return_val_if_fail (resource != NULL, FALSE);
1847
1848         if (!lm_connection_is_open (connection)) {
1849                 g_set_error (error,
1850                              LM_ERROR,
1851                              LM_ERROR_CONNECTION_NOT_OPEN,
1852                              "Connection is not open, call lm_connection_open() first");
1853                 return FALSE;
1854         }
1855
1856         connection->state = LM_CONNECTION_STATE_AUTHENTICATING;
1857
1858         m = connection_create_auth_req_msg (username);
1859         result = lm_connection_send_with_reply_and_block (connection, m, error);
1860         lm_message_unref (m);
1861
1862         if (!result) {
1863                 connection->state = LM_CONNECTION_STATE_OPEN;
1864                 return FALSE;
1865         }
1866
1867         m = connection_create_auth_msg (connection,
1868                                         username, 
1869                                         password,
1870                                         resource,
1871                                         connection_check_auth_type (result));
1872         lm_message_unref (result);
1873
1874         result = lm_connection_send_with_reply_and_block (connection, m, error);
1875         lm_message_unref (m);
1876
1877         if (!result) {
1878                 connection->state = LM_CONNECTION_STATE_OPEN;
1879                 return FALSE;
1880         }
1881
1882         type = lm_message_get_sub_type (result);
1883         lm_message_unref (result);
1884         
1885         switch (type) {
1886         case LM_MESSAGE_SUB_TYPE_RESULT:
1887                 connection->state = LM_CONNECTION_STATE_AUTHENTICATED;
1888                 return TRUE;
1889                 break;
1890         case LM_MESSAGE_SUB_TYPE_ERROR:
1891                 connection->state = LM_CONNECTION_STATE_OPEN;
1892                 g_set_error (error,
1893                              LM_ERROR,
1894                              LM_ERROR_AUTH_FAILED,
1895                              "Authentication failed");
1896                 return FALSE;
1897                 break;
1898         default:
1899                 g_assert_not_reached ();
1900                 break;
1901         } 
1902
1903         return FALSE;
1904 }
1905
1906 /**
1907  * lm_connection_set_keep_alive_rate:
1908  * @connection: #LmConnection to check if it is open.
1909  * @rate: Number of seconds between keep alive packages are sent.
1910  * 
1911  * Set the keep alive rate, in seconds. Set to 0 to prevent keep alive messages to be sent.
1912  * A keep alive message is a single space character.
1913  **/
1914 void
1915 lm_connection_set_keep_alive_rate (LmConnection *connection, guint rate)
1916 {
1917         g_return_if_fail (connection != NULL);
1918
1919         connection_stop_keep_alive (connection);
1920
1921         if (rate == 0) {
1922                 connection->keep_alive_id = 0;
1923                 return;
1924         }
1925
1926         connection->keep_alive_rate = rate * 1000;
1927         
1928         if (lm_connection_is_open (connection)) {
1929                 connection_start_keep_alive (connection);
1930         }
1931 }
1932
1933 /**
1934  * lm_connection_is_open:
1935  * @connection: #LmConnection to check if it is open.
1936  * 
1937  * Check if the @connection is currently open.
1938  * 
1939  * Return value: #TRUE if connection is open and #FALSE if it is closed.
1940  **/
1941 gboolean
1942 lm_connection_is_open (LmConnection *connection)
1943 {
1944         g_return_val_if_fail (connection != NULL, FALSE);
1945         
1946         return connection->state >= LM_CONNECTION_STATE_OPEN;
1947 }
1948
1949 /**
1950  * lm_connection_is_authenticated:
1951  * @connection: #LmConnection to check if it is authenticated
1952  * 
1953  * Check if @connection is authenticated.
1954  * 
1955  * Return value: #TRUE if connection is authenticated, #FALSE otherwise.
1956  **/
1957 gboolean 
1958 lm_connection_is_authenticated (LmConnection *connection)
1959 {
1960         g_return_val_if_fail (connection != NULL, FALSE);
1961
1962         return connection->state >= LM_CONNECTION_STATE_AUTHENTICATED;
1963 }
1964
1965 /**
1966  * lm_connection_get_server:
1967  * @connection: an #LmConnection
1968  * 
1969  * Fetches the server address that @connection is using. 
1970  * 
1971  * Return value: the server address
1972  **/
1973 const gchar *
1974 lm_connection_get_server (LmConnection *connection)
1975 {
1976         g_return_val_if_fail (connection != NULL, NULL);
1977
1978         return connection->server;
1979 }
1980
1981 /**
1982  * lm_connection_set_server:
1983  * @connection: an #LmConnection
1984  * @server: Address of the server
1985  * 
1986  * Sets the server address for @connection to @server. Notice that @connection
1987  * can't be open while doing this. 
1988  **/
1989 void
1990 lm_connection_set_server (LmConnection *connection, const gchar *server)
1991 {
1992         g_return_if_fail (connection != NULL);
1993         g_return_if_fail (server != NULL);
1994         
1995         if (lm_connection_is_open (connection)) {
1996                 g_warning ("Can't change server address while connected");
1997                 return;
1998         }
1999         
2000         g_free (connection->server);
2001         connection->server = _lm_utils_hostname_to_punycode (server);
2002 }
2003
2004 /**
2005  * lm_connection_get_jid:
2006  * @connection: an #LmConnection
2007  * 
2008  * Fetches the jid set for @connection is using. 
2009  * 
2010  * Return value: the jid
2011  **/
2012 const gchar *
2013 lm_connection_get_jid (LmConnection *connection)
2014 {
2015         g_return_val_if_fail (connection != NULL, NULL);
2016
2017         return connection->jid;
2018 }
2019
2020 /**
2021  * lm_connection_set_jid:
2022  * @connection: an #LmConnection
2023  * @jid: JID to be used for @connection
2024  * 
2025  * Sets the JID to be used for @connection.
2026  **/
2027 void 
2028 lm_connection_set_jid (LmConnection *connection, const gchar *jid)
2029 {
2030         g_return_if_fail (connection != NULL);
2031
2032         if (lm_connection_is_open (connection)) {
2033                 g_warning ("Can't change JID while connected");
2034                 return;
2035         }
2036
2037         g_free (connection->jid);
2038         connection->jid = g_strdup (jid);
2039 }
2040
2041 /**
2042  * lm_connection_get_port:
2043  * @connection: an #LmConnection
2044  * 
2045  * Fetches the port that @connection is using.
2046  * 
2047  * Return value: 
2048  **/
2049 guint
2050 lm_connection_get_port (LmConnection *connection)
2051 {
2052         g_return_val_if_fail (connection != NULL, 0);
2053
2054         return connection->port;
2055 }
2056
2057 /**
2058  * lm_connection_set_port:
2059  * @connection: an #LmConnection
2060  * @port: server port
2061  * 
2062  * Sets the server port that @connection will be using.
2063  **/
2064 void
2065 lm_connection_set_port (LmConnection *connection, guint port)
2066 {
2067         g_return_if_fail (connection != NULL);
2068         
2069         if (lm_connection_is_open (connection)) {
2070                 g_warning ("Can't change server port while connected");
2071                 return;
2072         }
2073         
2074         connection->port = port;
2075 }
2076
2077 /**
2078  * lm_connection_get_ssl: 
2079  * @connection: an #LmConnection
2080  *
2081  * Returns the SSL struct if the connection is using one.
2082  * 
2083  * Return value: The ssl struct or %NULL if no proxy is used.
2084  **/
2085 LmSSL *
2086 lm_connection_get_ssl (LmConnection *connection)
2087 {
2088         g_return_val_if_fail (connection != NULL, NULL);
2089         
2090         return connection->ssl;
2091 }
2092
2093 /**
2094  * lm_connection_set_ssl:
2095  * @connection: An #LmConnection
2096  * @ssl: An #LmSSL
2097  *
2098  * Sets SSL struct or unset if @ssl is %NULL. If set @connection will use SSL to for the connection.
2099  */
2100 void
2101 lm_connection_set_ssl (LmConnection *connection, LmSSL *ssl)
2102 {
2103         g_return_if_fail (connection != NULL);
2104         g_return_if_fail (lm_ssl_is_supported () == TRUE);
2105
2106         if (connection->ssl) {
2107                 lm_ssl_unref (connection->ssl);
2108         }
2109
2110         if (ssl) {
2111                 connection->ssl = lm_ssl_ref (ssl);
2112         } else {
2113                 connection->ssl = NULL;
2114         }
2115 }
2116
2117 /**
2118  * lm_connection_get_proxy: 
2119  * @connection: an #LmConnection
2120  *
2121  * Returns the proxy if the connection is using one.
2122  * 
2123  * Return value: The proxy or %NULL if no proxy is used.
2124  **/
2125 LmProxy *
2126 lm_connection_get_proxy (LmConnection *connection)
2127 {
2128         g_return_val_if_fail (connection != NULL, NULL);
2129
2130         return connection->proxy;
2131
2132
2133 /**
2134  * lm_connection_set_proxy: 
2135  * @connection: an #LmConnection
2136  * @proxy: an #LmProxy
2137  *
2138  * Sets the proxy to use for this connection. To unset pass #NULL.
2139  * 
2140  **/
2141 void
2142 lm_connection_set_proxy (LmConnection *connection, LmProxy *proxy)
2143 {
2144         g_return_if_fail (connection != NULL);
2145
2146         if (lm_connection_is_open (connection)) {
2147                 g_warning ("Can't change server proxy while connected");
2148                 return;
2149         }
2150
2151         if (connection->proxy) {
2152                 lm_proxy_unref (connection->proxy);
2153                 connection->proxy = NULL;
2154         }
2155
2156         if (proxy && lm_proxy_get_type (proxy) != LM_PROXY_TYPE_NONE) {
2157                 connection->proxy = lm_proxy_ref (proxy);
2158         }
2159 }
2160
2161 /**
2162  * lm_connection_send: 
2163  * @connection: #LmConnection to send message over.
2164  * @message: #LmMessage to send.
2165  * @error: location to store error, or %NULL
2166  * 
2167  * Asynchronous call to send a message.
2168  * 
2169  * Return value: Returns #TRUE if no errors where detected while sending, #FALSE otherwise.
2170  **/
2171 gboolean
2172 lm_connection_send (LmConnection  *connection, 
2173                     LmMessage     *message, 
2174                     GError       **error)
2175 {
2176         gchar    *xml_str;
2177         gchar    *ch;
2178         gboolean  result;
2179         
2180         g_return_val_if_fail (connection != NULL, FALSE);
2181         g_return_val_if_fail (message != NULL, FALSE);
2182         
2183         xml_str = lm_message_node_to_string (message->node);
2184         if ((ch = strstr (xml_str, "</stream:stream>"))) {
2185                 *ch = '\0';
2186         }
2187         
2188         result = connection_send (connection, xml_str, -1, error);
2189         g_free (xml_str);
2190
2191         return result;
2192 }
2193
2194 /**
2195  * lm_connection_send_with_reply:
2196  * @connection: #LmConnection used to send message.
2197  * @message: #LmMessage to send.
2198  * @handler: #LmMessageHandler that will be used when a reply to @message arrives
2199  * @error: location to store error, or %NULL
2200  * 
2201  * Send a #LmMessage which will result in a reply. 
2202  * 
2203  * Return value: Returns #TRUE if no errors where detected while sending, #FALSE otherwise.
2204  **/
2205 gboolean 
2206 lm_connection_send_with_reply (LmConnection      *connection,
2207                                LmMessage         *message,
2208                                LmMessageHandler  *handler,
2209                                GError           **error)
2210 {
2211         gchar *id;
2212         
2213         g_return_val_if_fail (connection != NULL, FALSE);
2214         g_return_val_if_fail (message != NULL, FALSE);
2215         g_return_val_if_fail (handler != NULL, FALSE);
2216
2217         if (lm_message_node_get_attribute (message->node, "id")) {
2218                 id = g_strdup (lm_message_node_get_attribute (message->node, 
2219                                                               "id"));
2220         } else {
2221                 id = _lm_utils_generate_id ();
2222                 lm_message_node_set_attributes (message->node, "id", id, NULL);
2223         }
2224         
2225         g_hash_table_insert (connection->id_handlers, 
2226                              id, lm_message_handler_ref (handler));
2227         
2228         return lm_connection_send (connection, message, error);
2229 }
2230
2231 /**
2232  * lm_connection_send_with_reply_and_block:
2233  * @connection: an #LmConnection
2234  * @message: an #LmMessage
2235  * @error: Set if error was detected during sending.
2236  * 
2237  * Send @message and wait for return.
2238  * 
2239  * Return value: The reply
2240  **/
2241 LmMessage *
2242 lm_connection_send_with_reply_and_block (LmConnection  *connection,
2243                                          LmMessage     *message,
2244                                          GError       **error)
2245 {
2246         gchar     *id;
2247         LmMessage *reply = NULL;
2248
2249         g_return_val_if_fail (connection != NULL, NULL);
2250         g_return_val_if_fail (message != NULL, NULL);
2251
2252         if (connection->state < LM_CONNECTION_STATE_OPENING) {
2253                 g_set_error (error,
2254                              LM_ERROR,
2255                              LM_ERROR_CONNECTION_NOT_OPEN,
2256                              "Connection is not open, call lm_connection_open() first");
2257                 return FALSE;
2258         }
2259
2260
2261         if (lm_message_node_get_attribute (message->node, "id")) {
2262                 id = g_strdup (lm_message_node_get_attribute (message->node, 
2263                                                               "id"));
2264         } else {
2265                 id = _lm_utils_generate_id ();
2266                 lm_message_node_set_attributes (message->node, "id", id, NULL);
2267         }
2268
2269         g_source_remove (g_source_get_id (connection->incoming_source));
2270         g_source_unref (connection->incoming_source);
2271         connection->incoming_source = NULL;
2272
2273         lm_connection_send (connection, message, error);
2274
2275         while (!reply) {
2276                 const gchar *m_id;
2277                 guint        n;
2278
2279                 g_main_context_iteration (connection->context, TRUE);
2280         
2281                 if (g_queue_is_empty (connection->incoming_messages)) {
2282                         continue;
2283                 }
2284
2285                 for (n = 0; n < g_queue_get_length (connection->incoming_messages); n++) {
2286                         LmMessage *m;
2287
2288                         m = (LmMessage *) g_queue_peek_nth (connection->incoming_messages, n);
2289
2290                         m_id = lm_message_node_get_attribute (m->node, "id");
2291                         
2292                         if (m_id && strcmp (m_id, id) == 0) {
2293                                 reply = m;
2294                                 g_queue_pop_nth (connection->incoming_messages,
2295                                                  n);
2296                                 break;
2297                         }
2298                 }
2299         }
2300
2301         g_free (id);
2302         connection->incoming_source = connection_create_source (connection);
2303         g_source_attach (connection->incoming_source, connection->context);
2304
2305         return reply;
2306 }
2307
2308 /**
2309  * lm_connection_register_message_handler:
2310  * @connection: Connection to register a handler for.
2311  * @handler: Message handler to register.
2312  * @type: Message type that @handler will handle.
2313  * @priority: The priority in which to call @handler.
2314  * 
2315  * Registers a #LmMessageHandler to handle incoming messages of a certain type.
2316  * To unregister the handler call lm_connection_unregister_message_handler().
2317  **/
2318 void
2319 lm_connection_register_message_handler  (LmConnection       *connection,
2320                                          LmMessageHandler   *handler,
2321                                          LmMessageType       type,
2322                                          LmHandlerPriority   priority)
2323 {
2324         HandlerData      *hd;
2325         
2326         g_return_if_fail (connection != NULL);
2327         g_return_if_fail (handler != NULL);
2328         g_return_if_fail (type != LM_MESSAGE_TYPE_UNKNOWN);
2329
2330         hd = g_new0 (HandlerData, 1);
2331         hd->priority = priority;
2332         hd->handler  = lm_message_handler_ref (handler);
2333
2334         connection->handlers[type] = g_slist_insert_sorted (connection->handlers[type],
2335                                                             hd, 
2336                                                             (GCompareFunc) connection_handler_compare_func);
2337 }
2338
2339 /**
2340  * lm_connection_unregister_message_handler:
2341  * @connection: Connection to unregister a handler for.
2342  * @handler: The handler to unregister.
2343  * @type: What type of messages to unregister this handler for.
2344  * 
2345  * Unregisters a handler for @connection. @handler will no longer be called 
2346  * when incoming messages of @type arrive.
2347  **/
2348 void
2349 lm_connection_unregister_message_handler (LmConnection      *connection,
2350                                           LmMessageHandler  *handler,
2351                                           LmMessageType      type)
2352 {
2353         GSList *l, *prev = NULL;
2354         
2355         g_return_if_fail (connection != NULL);
2356         g_return_if_fail (handler != NULL);
2357         g_return_if_fail (type != LM_MESSAGE_TYPE_UNKNOWN);
2358
2359         for (l = connection->handlers[type]; l; l = l->next) {
2360                 HandlerData *hd = (HandlerData *) l->data;
2361                 
2362                 if (hd->handler == handler) {
2363                         if (prev) {
2364                                 prev->next = l->next;
2365                         } else {
2366                                 connection->handlers[type] = l->next;
2367                         }
2368                         l->next = NULL;
2369                         g_slist_free (l);
2370                         lm_message_handler_unref (hd->handler);
2371                         g_free (hd);
2372                         break;
2373                 }
2374                 prev = l;
2375         }
2376 }
2377
2378 /**
2379  * lm_connection_set_disconnect_function:
2380  * @connection: Connection to register disconnect callback for.
2381  * @function: Function to be called when @connection is closed.
2382  * @user_data: User data passed to @function.
2383  * @notify: Function that will be called with @user_data when @user_data needs to be freed. Pass #NULL if it shouldn't be freed.
2384  * 
2385  * Set the callback that will be called when a connection is closed. 
2386  **/
2387 void
2388 lm_connection_set_disconnect_function (LmConnection         *connection,
2389                                        LmDisconnectFunction  function,
2390                                        gpointer              user_data,
2391                                        GDestroyNotify        notify)
2392 {
2393         g_return_if_fail (connection != NULL);
2394
2395         if (connection->disconnect_cb) {
2396                 _lm_utils_free_callback (connection->disconnect_cb);
2397         }
2398                 
2399         if (function) {
2400                 connection->disconnect_cb = _lm_utils_new_callback (function, 
2401                                                                     user_data,
2402                                                                     notify);
2403         } else {
2404                 connection->disconnect_cb = NULL;
2405         }
2406 }
2407
2408 /**
2409  * lm_connection_send_raw:
2410  * @connection: Connection used to send
2411  * @str: The string to send, the entire string will be sent.
2412  * @error: Set if error was detected during sending.
2413  * 
2414  * Asynchronous call to send a raw string. Useful for debugging and testing.
2415  * 
2416  * Return value: Returns #TRUE if no errors was detected during sending, 
2417  * #FALSE otherwise.
2418  **/
2419 gboolean 
2420 lm_connection_send_raw (LmConnection  *connection, 
2421                         const gchar   *str, 
2422                         GError       **error)
2423 {
2424         g_return_val_if_fail (connection != NULL, FALSE);
2425         g_return_val_if_fail (str != NULL, FALSE);
2426
2427         return connection_send (connection, str, -1, error);
2428 }
2429 /**
2430  * lm_connection_get_state:
2431  * @connection: Connection to get state on
2432  *
2433  * Returns the state of the connection.
2434  *
2435  * Return value: The state of the connection.
2436  **/
2437 LmConnectionState 
2438 lm_connection_get_state (LmConnection *connection)
2439 {
2440         g_return_val_if_fail (connection != NULL, 
2441                               LM_CONNECTION_STATE_CLOSED);
2442
2443         return connection->state;
2444 }
2445
2446 /**
2447  * lm_connection_ref:
2448  * @connection: Connection to add a reference to.
2449  * 
2450  * Add a reference on @connection. To remove a reference call 
2451  * lm_connection_unref().
2452  * 
2453  * Return value: Returns the same connection.
2454  **/
2455 LmConnection*
2456 lm_connection_ref (LmConnection *connection)
2457 {
2458         g_return_val_if_fail (connection != NULL, NULL);
2459         
2460         connection->ref_count++;
2461         
2462         return connection;
2463 }
2464
2465 /**
2466  * lm_connection_unref:
2467  * @connection: Connection to remove reference from.
2468  * 
2469  * Removes a reference on @connection. If there are no references to
2470  * @connection it will be freed and shouldn't be used again.
2471  **/
2472 void
2473 lm_connection_unref (LmConnection *connection)
2474 {
2475         g_return_if_fail (connection != NULL);
2476         
2477         connection->ref_count--;
2478         
2479         if (connection->ref_count == 0) {
2480                 connection_free (connection);
2481         }
2482 }
2483