loudmouth/src/lm-socket.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
       
     2 /*
       
     3  * Copyright (C) 2006 Imendio AB
       
     4  *  and/or its subsidiary/subsidiaries. All rights reserved.
       
     5  * Copyright (C) 2007 Collabora Ltd.
       
     6  *
       
     7  * This program is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Lesser General Public License as
       
     9  * published by the Free Software Foundation; either version 2 of the
       
    10  * License, or (at your option) any later version.
       
    11  *
       
    12  * This program is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Lesser General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Lesser General Public
       
    18  * License along with this program; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 #include <config.h>
       
    24 
       
    25 #include <string.h>
       
    26 #include <sys/types.h>
       
    27 
       
    28 /* Needed on Mac OS X */
       
    29 #if HAVE_NETINET_IN_H
       
    30 #include <netinet/in.h>
       
    31 #endif
       
    32 
       
    33 /* Needed on Mac OS X */
       
    34 #if HAVE_ARPA_NAMESER_COMPAT_H
       
    35 #include <arpa/nameser_compat.h>
       
    36 #endif
       
    37 
       
    38 #include <arpa/nameser.h>
       
    39 #include <resolv.h>
       
    40 
       
    41 #include "lm-debug.h"
       
    42 #include "lm-internals.h"
       
    43 #include "lm-misc.h"
       
    44 #include "lm-ssl.h"
       
    45 #include "lm-ssl-internals.h"
       
    46 #include "lm-proxy.h"
       
    47 #include "lm-socket.h"
       
    48 #include "lm-sock.h"
       
    49 #include "lm-error.h"
       
    50 
       
    51 #ifdef HAVE_ASYNCNS
       
    52 #include <asyncns.h>
       
    53 #define freeaddrinfo(x) asyncns_freeaddrinfo(x)
       
    54 #endif
       
    55 
       
    56 #define IN_BUFFER_SIZE 1024
       
    57 #define MIN_PORT 1
       
    58 #define MAX_PORT 65536
       
    59 //#define SRV_LEN 8192
       
    60 #define SRV_LEN 512 // check the actual value needed here! - meco
       
    61 
       
    62 struct _LmSocket {
       
    63 	LmConnection *connection;
       
    64 	GMainContext *context;
       
    65 
       
    66 	gchar        *domain;
       
    67 	gchar        *server;
       
    68 	guint         port;
       
    69 
       
    70 	gboolean      blocking;
       
    71 
       
    72 	LmSSL        *ssl;
       
    73 	gboolean      ssl_started;
       
    74 	LmProxy      *proxy;
       
    75 
       
    76 	GIOChannel   *io_channel;
       
    77 	GSource      *watch_in;
       
    78 	GSource      *watch_err;
       
    79 	GSource      *watch_hup;
       
    80 
       
    81 	LmSocketT      fd;
       
    82 
       
    83 	GSource      *watch_connect;
       
    84 
       
    85 	gboolean      cancel_open;
       
    86 	
       
    87 	GSource      *watch_out;
       
    88 	GString      *out_buf;
       
    89 
       
    90 	LmConnectData *connect_data;
       
    91 
       
    92 	IncomingDataFunc data_func;
       
    93 	SocketClosedFunc closed_func;
       
    94 	ConnectResultFunc connect_func;
       
    95 	gpointer         user_data;
       
    96 
       
    97 	guint          ref_count;
       
    98 
       
    99 #ifdef HAVE_ASYNCNS
       
   100 	GSource		*watch_resolv;
       
   101 	asyncns_query_t *resolv_query;
       
   102 	asyncns_t	*asyncns_ctx;
       
   103 	GIOChannel	*resolv_channel;
       
   104 #endif
       
   105 }; 
       
   106 
       
   107 static void         socket_free               (LmSocket       *socket);
       
   108 static gboolean     socket_do_connect         (LmConnectData  *connect_data);
       
   109 static gboolean     socket_connect_cb         (GIOChannel     *source, 
       
   110 					       GIOCondition    condition,
       
   111 					       LmConnectData  *connect_data);
       
   112 static gboolean     socket_in_event           (GIOChannel     *source,
       
   113 					       GIOCondition    condition,
       
   114 					       LmSocket       *socket);
       
   115 static gboolean     socket_hup_event          (GIOChannel     *source,
       
   116 					       GIOCondition    condition,
       
   117 					       LmSocket       *socket);
       
   118 static gboolean     socket_error_event        (GIOChannel     *source,
       
   119 					       GIOCondition    condition,
       
   120 					       LmSocket       *socket);
       
   121 static gboolean     socket_buffered_write_cb  (GIOChannel     *source, 
       
   122 					       GIOCondition    condition,
       
   123 					       LmSocket       *socket);
       
   124 static gboolean     socket_parse_srv_response (unsigned char  *srv, 
       
   125 					       int             srv_len, 
       
   126 					       gchar         **out_server, 
       
   127 					       guint          *out_port);
       
   128 static void         socket_close_io_channel   (GIOChannel     *io_channel);
       
   129 
       
   130 static void
       
   131 socket_free (LmSocket *socket)
       
   132 {
       
   133 	g_free (socket->server);
       
   134 	g_free (socket->domain);
       
   135 
       
   136 	if (socket->ssl) {
       
   137 		lm_ssl_unref (socket->ssl);
       
   138 	}
       
   139 
       
   140 	if (socket->proxy) {
       
   141 		lm_proxy_unref (socket->proxy);
       
   142 	}
       
   143 	
       
   144 	if (socket->out_buf) {
       
   145 		g_string_free (socket->out_buf, TRUE);
       
   146 	}
       
   147 
       
   148 	g_free (socket);
       
   149 }
       
   150 
       
   151 gint
       
   152 lm_socket_do_write (LmSocket *socket, const gchar *buf, gint len)
       
   153 {
       
   154 	gint b_written;
       
   155 	gint err;
       
   156 	if (socket->ssl_started) {
       
   157 		b_written = _lm_ssl_send (socket->ssl, buf, len);
       
   158 	} else {
       
   159 		GIOStatus io_status = G_IO_STATUS_AGAIN;
       
   160 		gsize     bytes_written;
       
   161 
       
   162 		while (io_status == G_IO_STATUS_AGAIN) {
       
   163 			io_status = g_io_channel_write_chars (socket->io_channel, 
       
   164 							      buf, len, 
       
   165 							      &bytes_written,
       
   166 							      NULL);
       
   167 		}
       
   168 
       
   169 		b_written = bytes_written;
       
   170 
       
   171 		if (io_status != G_IO_STATUS_NORMAL) {
       
   172 			b_written = -1;
       
   173 		}
       
   174 	}
       
   175 
       
   176 	err = _lm_sock_get_last_error ();
       
   177 	lm_verbose("[lm_socket_do_write]: socket write last error: %d\n\n",err);
       
   178 	return b_written;
       
   179 }
       
   180 
       
   181 static gboolean
       
   182 socket_read_incoming (LmSocket *socket,
       
   183 		      gchar    *buf,
       
   184 		      gsize     buf_size,
       
   185 		      gsize    *bytes_read,
       
   186 		      gboolean *hangup,
       
   187 		      gint     *reason)
       
   188 {
       
   189 	GIOStatus status;
       
   190 
       
   191 	*hangup = FALSE;
       
   192 
       
   193 	if (socket->ssl_started) {
       
   194 		status = _lm_ssl_read (socket->ssl, 
       
   195 				       buf, buf_size - 1, bytes_read);
       
   196 	} else {
       
   197 		status = g_io_channel_read_chars (socket->io_channel,
       
   198 						  buf, buf_size - 1,
       
   199 						  bytes_read,
       
   200 						  NULL);
       
   201 	}
       
   202 
       
   203 //added by prima
       
   204 	if (status != G_IO_STATUS_NORMAL ) {
       
   205 		switch (status) {
       
   206 		case G_IO_STATUS_EOF:
       
   207 			*reason = LM_DISCONNECT_REASON_HUP;
       
   208 			break;
       
   209 		case G_IO_STATUS_AGAIN:
       
   210 			/* No data readable but we didn't hangup */
       
   211 			return FALSE;
       
   212 		//	break;
       
   213 		case G_IO_STATUS_ERROR:
       
   214 			*reason = LM_DISCONNECT_REASON_ERROR;
       
   215 			break;
       
   216 		default:
       
   217 			*reason = LM_DISCONNECT_REASON_UNKNOWN;
       
   218 		}
       
   219 
       
   220 		/* Notify connection_in_event that we hangup the connection */
       
   221 		*hangup = TRUE;
       
   222 		
       
   223 		return FALSE;
       
   224 	}
       
   225 
       
   226 	if(*bytes_read>0)
       
   227 		{
       
   228 		buf[*bytes_read] = '\0';	
       
   229 		return TRUE;
       
   230 		}	
       
   231 
       
   232 	/* There is more data to be read */
       
   233 	return FALSE;
       
   234 	//return TRUE;
       
   235 }
       
   236 
       
   237 static gboolean
       
   238 socket_in_event (GIOChannel   *source,
       
   239 		     GIOCondition  condition,
       
   240 		     LmSocket     *socket)
       
   241 {
       
   242 	gchar     buf[IN_BUFFER_SIZE];
       
   243 	gsize     bytes_read = 0;
       
   244 	gboolean  read_anything = FALSE;
       
   245 	gboolean  hangup = 0;
       
   246 	gint      reason = 0;
       
   247 
       
   248 	if (!socket->io_channel) {
       
   249 		lm_verbose ( "[socket_in_event]:Error in io_channel\n");
       
   250 		return FALSE;
       
   251 	}
       
   252 
       
   253 	while (/*(condition & G_IO_IN) && */socket_read_incoming (socket, buf, IN_BUFFER_SIZE, 
       
   254 				     &bytes_read, &hangup, &reason)) {
       
   255 		
       
   256 		//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "\nRECV [%d]:\n", 
       
   257 		//       (int)bytes_read);
       
   258 		//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   259 		//       "-----------------------------------\n");
       
   260 		//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "'%s'\n", buf);
       
   261 		//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   262 		//       "-----------------------------------\n");
       
   263 		
       
   264 		lm_verbose ("\n[socket_in_event]: RECV [%d]:\n", (int)bytes_read);
       
   265 		lm_verbose ("-----------------------------------\n");
       
   266 		lm_verbose ("'%s'\n", buf);
       
   267 		lm_verbose ( "-----------------------------------\n");
       
   268 		lm_verbose ("Read: %d chars\n", (int)bytes_read);
       
   269 
       
   270 		(socket->data_func) (socket, buf, socket->user_data);
       
   271 
       
   272 		read_anything = TRUE;
       
   273 
       
   274 		//condition = g_io_channel_get_buffer_condition (socket->io_channel);
       
   275 	}
       
   276 
       
   277 	/* If we have read something, delay the hangup so that the data can be
       
   278 	 * processed. */
       
   279 	if (hangup && !read_anything) {
       
   280 		(socket->closed_func) (socket, reason, socket->user_data);
       
   281 		lm_verbose ( "[socket_in_event]:Error in hangup && !read_anything\n");
       
   282 		return FALSE;
       
   283 	}
       
   284 lm_verbose ( "[socket_in_event]:Returning TRUE\n");
       
   285 	return TRUE;
       
   286 }
       
   287 	
       
   288 static gboolean
       
   289 socket_hup_event (GIOChannel   *source,
       
   290 		      GIOCondition  condition,
       
   291 		      LmSocket     *socket)
       
   292 {
       
   293 	lm_verbose ("HUP event: %d->'%s'\n", 
       
   294 		    condition, lm_misc_io_condition_to_str (condition));
       
   295 
       
   296 	if (!socket->io_channel) {
       
   297 		return FALSE;
       
   298 	}
       
   299 
       
   300 	(socket->closed_func) (socket, LM_DISCONNECT_REASON_HUP, 
       
   301 			       socket->user_data);
       
   302 	
       
   303 	return TRUE;
       
   304 }
       
   305 
       
   306 static gboolean
       
   307 socket_error_event (GIOChannel   *source,
       
   308 		    GIOCondition  condition,
       
   309 		    LmSocket     *socket)
       
   310 {
       
   311 	gint err =0;
       
   312 	lm_verbose ("[socket_error_event]: ERROR event: %d->'%s'\n", 
       
   313 		    condition, lm_misc_io_condition_to_str (condition));
       
   314 
       
   315 	err = _lm_sock_get_last_error ();
       
   316 	lm_verbose("[socket_error_event]: socket write last error: %d\n\n",err);
       
   317 	if (!socket->io_channel) {
       
   318 		return FALSE;
       
   319 	}
       
   320 
       
   321 	(socket->closed_func) (socket, LM_DISCONNECT_REASON_ERROR, 
       
   322 			       socket->user_data);
       
   323 	
       
   324 	return TRUE;
       
   325 }
       
   326 
       
   327 static gboolean
       
   328 _lm_socket_ssl_init (LmSocket *socket, gboolean delayed)
       
   329 {
       
   330 	GError *error = NULL;
       
   331 	const gchar *ssl_verify_domain = NULL;
       
   332 
       
   333 	lm_verbose ("[_lm_socket_ssl_init] Setting up SSL...\n");
       
   334 
       
   335 	_lm_ssl_initialize (socket->ssl);
       
   336 
       
   337 #ifdef HAVE_GNUTLS
       
   338 	/* GNU TLS requires the socket to be blocking */
       
   339 	_lm_sock_set_blocking (socket->fd, TRUE);
       
   340 #endif
       
   341 
       
   342 	/* If we're using StartTLS, the correct thing is to verify against
       
   343 	 * the domain. If we're using old SSL, we should verify against the
       
   344 	 * hostname. */
       
   345 	if (delayed)
       
   346 		ssl_verify_domain = socket->domain;
       
   347 	else
       
   348 		ssl_verify_domain = socket->server;
       
   349 	
       
   350 	if (!_lm_ssl_begin (socket->ssl, socket->fd, ssl_verify_domain, &error)) {
       
   351 		lm_verbose ("Could not begin SSL\n");
       
   352 
       
   353 		if (error) {
       
   354 			/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   355 				"%s\n", error->message);
       
   356 			*/
       
   357 			lm_verbose("[_lm_socket_ssl_init]: %s\n", error->message);
       
   358 				g_error_free (error);
       
   359 		}
       
   360 		lm_verbose("\n[_lm_socket_ssl_init]: shutting down the socket");
       
   361 		_lm_sock_shutdown (socket->fd);
       
   362 		_lm_sock_close (socket->fd);
       
   363 
       
   364 		if (!delayed && socket->connect_func) {
       
   365 			lm_verbose("\n[_lm_socket_ssl_init]: calling the socket connect callback if ssl begin failed");
       
   366 			(socket->connect_func) (socket, FALSE, socket->user_data);
       
   367 		}
       
   368 		
       
   369 		return FALSE;
       
   370 	}
       
   371 
       
   372 #ifdef HAVE_GNUTLS
       
   373 	_lm_sock_set_blocking (socket->fd, FALSE); 
       
   374 #endif
       
   375 
       
   376 	socket->ssl_started = TRUE;
       
   377 
       
   378   return TRUE;
       
   379 }
       
   380 
       
   381 gboolean
       
   382 lm_socket_starttls (LmSocket *socket)
       
   383 {
       
   384 	g_return_val_if_fail (lm_ssl_get_use_starttls (socket->ssl) == TRUE, FALSE);
       
   385 
       
   386 	return _lm_socket_ssl_init (socket, TRUE);
       
   387 }
       
   388 
       
   389 
       
   390 
       
   391 void
       
   392 _lm_socket_succeeded (LmConnectData *connect_data)
       
   393 {
       
   394 	LmSocket     *socket;
       
   395 	
       
   396 	socket = connect_data->socket;
       
   397 
       
   398 	lm_verbose ("\n[_lm_socket_succeeded]:inside.. \n");
       
   399 	if (socket->watch_connect) {
       
   400 		g_source_destroy (socket->watch_connect);
       
   401 		socket->watch_connect = NULL;
       
   402 	}
       
   403 
       
   404 	/* Need some way to report error/success */
       
   405 	if (socket->cancel_open) {
       
   406 		lm_verbose ("Cancelling connection...\n");
       
   407 		if (socket->connect_func) {
       
   408 			(socket->connect_func) (socket, FALSE, socket->user_data);
       
   409 		}
       
   410 		return;
       
   411 	}
       
   412 	
       
   413 	socket->fd = connect_data->fd;
       
   414 	socket->io_channel = connect_data->io_channel;
       
   415 
       
   416 	freeaddrinfo (connect_data->resolved_addrs);
       
   417 	socket->connect_data = NULL;
       
   418 	g_free (connect_data);
       
   419 
       
   420 	/* old-style ssl should be started immediately */
       
   421 	if (socket->ssl && (lm_ssl_get_use_starttls (socket->ssl) == FALSE)) {
       
   422 		if (!_lm_socket_ssl_init (socket, FALSE)) {
       
   423 			return;
       
   424 		}
       
   425 	}
       
   426 
       
   427 	socket->watch_in = 
       
   428 		lm_misc_add_io_watch (socket->context,
       
   429 				      socket->io_channel,
       
   430 				      G_IO_IN,
       
   431 				      (GIOFunc) socket_in_event,
       
   432 				      socket);
       
   433 
       
   434 	/* FIXME: if we add these, we don't get ANY
       
   435 	 * response from the server, this is to do with the way that
       
   436 	 * windows handles watches, see bug #331214.
       
   437 	 */
       
   438 #ifndef G_OS_WIN32
       
   439 	socket->watch_err = 
       
   440 		lm_misc_add_io_watch (socket->context,
       
   441 				      socket->io_channel,
       
   442 				      G_IO_ERR,
       
   443 				      (GIOFunc) socket_error_event,
       
   444 				      socket);
       
   445 		
       
   446 	socket->watch_hup =
       
   447 		lm_misc_add_io_watch (socket->context,
       
   448 				      socket->io_channel,
       
   449 				      G_IO_HUP,
       
   450 				      (GIOFunc) socket_hup_event,
       
   451 				      socket);
       
   452 #endif
       
   453 
       
   454 	if (socket->connect_func) {
       
   455 		(socket->connect_func) (socket, TRUE, socket->user_data);
       
   456 	}
       
   457 }
       
   458 
       
   459 gboolean 
       
   460 _lm_socket_failed_with_error (LmConnectData *connect_data, int error) 
       
   461 {
       
   462 	LmSocket *socket;
       
   463 	
       
   464 	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   465 	       "Connection failed: %s (error %d)\n",
       
   466 	       _lm_sock_get_error_str (error), error);*/
       
   467 	lm_verbose( "[_lm_socket_failed_with_error]: Connection failed: %s (error %d)\n",_lm_sock_get_error_str (error), error);
       
   468 	
       
   469 	socket = lm_socket_ref (connect_data->socket);
       
   470 
       
   471 	connect_data->current_addr = connect_data->current_addr->ai_next;
       
   472 	
       
   473 	if (socket->watch_connect) {
       
   474 		g_source_destroy (socket->watch_connect);
       
   475 		socket->watch_connect = NULL;
       
   476 	}
       
   477 
       
   478 	if (connect_data->io_channel != NULL) {
       
   479 		socket_close_io_channel (connect_data->io_channel);
       
   480 	}
       
   481 	
       
   482 	if (connect_data->current_addr == NULL) {
       
   483 		if (socket->connect_func) {
       
   484 			(socket->connect_func) (socket, FALSE, socket->user_data);
       
   485 		}
       
   486 		lm_verbose("\n\n[_lm_socket_failed_with_error]: connect_data->current_addr ==NULL");
       
   487 		 /* if the user callback called connection_close(), this is already freed */
       
   488 		if (socket->connect_data != NULL) {
       
   489 			freeaddrinfo (connect_data->resolved_addrs);
       
   490 			socket->connect_data = NULL;
       
   491 			g_free (connect_data);
       
   492 		}
       
   493 	} else {
       
   494 		/* try to connect to the next host */
       
   495 		lm_verbose("\n\n[_lm_socket_failed_with_error]: !!!!Trying to connect to the next host after socket connect failed with error\n");
       
   496 		return socket_do_connect (connect_data);
       
   497 	}
       
   498 
       
   499 	lm_socket_unref(socket);
       
   500 
       
   501 	return FALSE;
       
   502 }
       
   503 
       
   504 gboolean 
       
   505 _lm_socket_failed (LmConnectData *connect_data)
       
   506 {
       
   507 	return _lm_socket_failed_with_error (connect_data,
       
   508                                        _lm_sock_get_last_error());
       
   509 }
       
   510 
       
   511 static gboolean 
       
   512 socket_connect_cb (GIOChannel   *source, 
       
   513 		       GIOCondition  condition,
       
   514 		       LmConnectData *connect_data) 
       
   515 {
       
   516 	LmSocket        *socket;
       
   517 	struct addrinfo *addr;
       
   518 	int              err;
       
   519 	socklen_t        len;
       
   520 	LmSocketT        fd;
       
   521 	gboolean         result = FALSE;
       
   522 
       
   523 	socket = lm_socket_ref (connect_data->socket);
       
   524 	addr = connect_data->current_addr;
       
   525 	fd = g_io_channel_unix_get_fd (source);
       
   526 	lm_verbose("\n[socket_connect_cb]: Inside socket_connect_cb\n");
       
   527 	if (condition == G_IO_ERR) {
       
   528 		len = sizeof (err);
       
   529 		_lm_sock_get_error (fd, &err, &len);
       
   530 		if (!_lm_sock_is_blocking_error (err)) {
       
   531 			/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   532 			       "Connection failed.\n");*/
       
   533 			lm_verbose( "[socket_conect_cb]: Connection failed.\n");
       
   534 
       
   535 			/* error condition, but might be possible to recover
       
   536 			 * from it (by connecting to the next host) */
       
   537 			if (!_lm_socket_failed_with_error (connect_data, err)) {
       
   538 				socket->watch_connect = NULL;
       
   539 				goto out;
       
   540 			}
       
   541 		}
       
   542 	}
       
   543 
       
   544 	if (_lm_connection_async_connect_waiting (socket->connection)) {
       
   545 		gint res;
       
   546 
       
   547 		fd = g_io_channel_unix_get_fd (source);
       
   548 		lm_verbose("\n[socket_conect_cb]: Async waiting calling _lm_sock_connect again\n");
       
   549 		res = _lm_sock_connect (fd, addr->ai_addr, (int)addr->ai_addrlen);  
       
   550 		if (res < 0) {
       
   551 			err = _lm_sock_get_last_error ();
       
   552 			if (_lm_sock_is_blocking_success (err)) {
       
   553 				_lm_connection_set_async_connect_waiting (socket->connection, FALSE);
       
   554 
       
   555 				/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   556 				       "Connection success (1).\n");*/
       
   557 				lm_verbose("[socket_connect_cb]: connection success");
       
   558 				_lm_socket_succeeded (connect_data);
       
   559 			}
       
   560 			
       
   561 			if (_lm_connection_async_connect_waiting (socket->connection) &&
       
   562 			    !_lm_sock_is_blocking_error (err)) {
       
   563 				/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   564 				       "Connection failed.\n");*/
       
   565 				lm_verbose("[socket_conect_cb]: connection failed");
       
   566 				_lm_sock_close (connect_data->fd);
       
   567 				_lm_socket_failed_with_error (connect_data, err);
       
   568 
       
   569 				socket->watch_connect = NULL;
       
   570 				goto out;
       
   571 			}
       
   572 		} 
       
   573 	} else {		
       
   574 		/* for blocking sockets, G_IO_OUT means we are connected */
       
   575 		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   576 		       "Connection success (2).\n");*/
       
   577 		lm_verbose("[socket_conect_cb]: Connection success (2).\n");
       
   578 		_lm_socket_succeeded (connect_data);
       
   579 	}
       
   580 
       
   581 	result = TRUE;
       
   582 
       
   583  out:
       
   584 	lm_socket_unref(socket);
       
   585 	
       
   586  	return result; 
       
   587 }
       
   588 
       
   589 static gboolean
       
   590 socket_do_connect (LmConnectData *connect_data) 
       
   591 {
       
   592 	LmSocket        *socket;
       
   593 	LmSocketT        fd;
       
   594 	int              res, err;
       
   595 	int              port;
       
   596 	char             name[NI_MAXHOST];
       
   597 	char             portname[NI_MAXSERV];
       
   598 	struct addrinfo *addr;
       
   599 	
       
   600 	socket = connect_data->socket;
       
   601 	addr = connect_data->current_addr;
       
   602  
       
   603 	if (socket->proxy) {
       
   604 		port = htons (lm_proxy_get_port (socket->proxy));
       
   605 	} else {
       
   606 		port = htons (socket->port);
       
   607 	}
       
   608 	
       
   609 	((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
       
   610 
       
   611 	res = getnameinfo (addr->ai_addr,
       
   612 			   (socklen_t)addr->ai_addrlen,
       
   613 			   name,     sizeof (name),
       
   614 			   portname, sizeof (portname),
       
   615 			   NI_NUMERICHOST | NI_NUMERICSERV);
       
   616 	
       
   617 	if (res < 0) {
       
   618 		return _lm_socket_failed (connect_data);
       
   619 	}
       
   620 
       
   621 	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   622 	       "Trying %s port %s...\n", name, portname);*/
       
   623 	lm_verbose("[socket_do_connect]: Trying %s port %s...\n", name, portname);
       
   624 	lm_verbose("[socket_do_connect]: calling make socket\n");
       
   625 	fd = _lm_sock_makesocket (addr->ai_family,
       
   626 				  addr->ai_socktype, 
       
   627 				  addr->ai_protocol);
       
   628 	lm_verbose("[socket_do_connet]: called make socket and fd");
       
   629 	lm_verbose("[socket_do_connect]: The value of FD is :%d",fd);
       
   630 	if (!_LM_SOCK_VALID (fd)) {
       
   631 		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   632 		       "Failed making socket, error:%d...\n",
       
   633 		       _lm_sock_get_last_error ());*/
       
   634 		lm_verbose( "[socket_do_connect]: Failed making socket, error:[%d]...\n", _lm_sock_get_last_error ());
       
   635 
       
   636 		return _lm_socket_failed (connect_data);
       
   637 	}
       
   638 
       
   639 	/* Even though it says _unix_new(), it is supported by glib on
       
   640 	 * win32 because glib does some cool stuff to find out if it
       
   641 	 * can treat it as a FD or a windows SOCKET.
       
   642 	 */
       
   643 	connect_data->fd = fd;
       
   644 	connect_data->io_channel = g_io_channel_unix_new (fd);
       
   645 	
       
   646 	g_io_channel_set_encoding (connect_data->io_channel, NULL, NULL);
       
   647 	g_io_channel_set_buffered (connect_data->io_channel, FALSE);
       
   648 
       
   649 	//_lm_sock_set_blocking (connect_data->fd, socket->blocking);
       
   650 	
       
   651 	if (socket->proxy) {
       
   652 		socket->watch_connect =
       
   653 			lm_misc_add_io_watch (socket->context,
       
   654 					      connect_data->io_channel,
       
   655 					      G_IO_OUT|G_IO_ERR,
       
   656 					      (GIOFunc) _lm_proxy_connect_cb, 
       
   657 					      connect_data);
       
   658 	} else {
       
   659 		socket->watch_connect =
       
   660 			lm_misc_add_io_watch (socket->context,
       
   661 					      connect_data->io_channel,
       
   662 					      G_IO_OUT|G_IO_ERR,
       
   663 					      (GIOFunc) socket_connect_cb,
       
   664 					      connect_data);
       
   665 	}
       
   666 
       
   667 	_lm_connection_set_async_connect_waiting (socket->connection, !socket->blocking);
       
   668 	lm_verbose("\n[socket_do_connect]: calling _lm_sock_connect\n");
       
   669   	_lm_sock_set_blocking (connect_data->fd, TRUE); //prima
       
   670   	errno =0;
       
   671   	res = _lm_sock_connect (connect_data->fd, 
       
   672 				addr->ai_addr, (int)addr->ai_addrlen);  
       
   673 	err = _lm_sock_get_last_error (); 
       
   674 	lm_verbose("[socket_do_connect]: socket connect last error: [%d]\n",err);
       
   675 	if (res < 0) {
       
   676 		//err = _lm_sock_get_last_error ();
       
   677 		lm_verbose("[socket_do_connect]: socket connect last error: %d\n",err);
       
   678 		if (!_lm_sock_is_blocking_error (err)) {
       
   679 			_lm_sock_close (connect_data->fd);
       
   680 			return _lm_socket_failed_with_error (connect_data, err);
       
   681 		}
       
   682 	}
       
   683 	_lm_sock_set_blocking (connect_data->fd, FALSE);//prima
       
   684 	return TRUE;
       
   685 }
       
   686 
       
   687 gboolean
       
   688 lm_socket_output_is_buffered (LmSocket     *socket,
       
   689 			       const gchar  *buffer,
       
   690 			       gint          len)
       
   691 {
       
   692 	if (socket->out_buf) {
       
   693 		lm_verbose ("Appending %d bytes to output buffer\n", len);
       
   694 		g_string_append_len (socket->out_buf, buffer, len);
       
   695 		return TRUE;
       
   696 	}
       
   697 
       
   698 	return FALSE;
       
   699 }
       
   700 
       
   701 void
       
   702 lm_socket_setup_output_buffer (LmSocket *socket, const gchar *buffer, gint len)
       
   703 {
       
   704 	lm_verbose ("OUTPUT BUFFER ENABLED\n");
       
   705 
       
   706 	socket->out_buf = g_string_new_len (buffer, len);
       
   707 
       
   708 	socket->watch_out =
       
   709 		lm_misc_add_io_watch (socket->context,
       
   710 				      socket->io_channel,
       
   711 				      G_IO_OUT,
       
   712 				      (GIOFunc) socket_buffered_write_cb,
       
   713 				      socket);
       
   714 }
       
   715 
       
   716 static gboolean
       
   717 socket_buffered_write_cb (GIOChannel   *source, 
       
   718 			  GIOCondition  condition,
       
   719 			  LmSocket     *socket)
       
   720 {
       
   721 	gint     b_written;
       
   722 	GString *out_buf;
       
   723 	/* FIXME: Do the writing */
       
   724 
       
   725 	out_buf = socket->out_buf;
       
   726 	if (!out_buf) {
       
   727 		/* Should not be possible */
       
   728 		return FALSE;
       
   729 	}
       
   730 
       
   731 	b_written = lm_socket_do_write (socket, out_buf->str, out_buf->len);
       
   732 
       
   733 	if (b_written < 0) {
       
   734 		(socket->closed_func) (socket, LM_DISCONNECT_REASON_ERROR, 
       
   735 				       socket->user_data);
       
   736 		return FALSE;
       
   737 	}
       
   738 
       
   739 	g_string_erase (out_buf, 0, (gsize) b_written);
       
   740 	if (out_buf->len == 0) {
       
   741 		lm_verbose ("Output buffer is empty, going back to normal output\n");
       
   742 
       
   743 		if (socket->watch_out) {
       
   744 			g_source_destroy (socket->watch_out);
       
   745 			socket->watch_out = NULL;
       
   746 		}
       
   747 
       
   748 		g_string_free (out_buf, TRUE);
       
   749 		socket->out_buf = NULL;
       
   750 		return FALSE;
       
   751 	}
       
   752 
       
   753 	return TRUE;
       
   754 }
       
   755 
       
   756 static gboolean
       
   757 socket_parse_srv_response (unsigned char  *srv, 
       
   758 			   int             srv_len, 
       
   759 			   gchar         **out_server, 
       
   760 			   guint          *out_port)
       
   761 {
       
   762 /*	int                  qdcount;
       
   763 	int                  ancount;
       
   764 	int                  len;
       
   765 	const unsigned char *pos;
       
   766 	unsigned char       *end;
       
   767 	HEADER              *head;
       
   768 	char                 name[256];
       
   769 	char                 pref_name[256];
       
   770 	guint                pref_port = 0;
       
   771 	guint                pref_prio = 9999;
       
   772 
       
   773 	pref_name[0] = 0;
       
   774 
       
   775 	pos = srv + sizeof (HEADER);
       
   776 	end = srv + srv_len;
       
   777 	head = (HEADER *) srv;
       
   778 
       
   779 	qdcount = ntohs (head->qdcount);
       
   780 	ancount = ntohs (head->ancount);
       
   781 
       
   782 	// Ignore the questions 
       
   783 	while (qdcount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
       
   784 		g_assert (len >= 0);
       
   785 		pos += len + QFIXEDSZ;
       
   786 	}
       
   787 
       
   788 	// Parse the answers 
       
   789 	while (ancount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
       
   790 		// Ignore the initial string 
       
   791 		uint16_t pref, weight, port;
       
   792 
       
   793 		g_assert (len >= 0);
       
   794 		pos += len;
       
   795 		// Ignore type, ttl, class and dlen 
       
   796 		pos += 10;
       
   797 		GETSHORT (pref, pos);
       
   798 		GETSHORT (weight, pos);
       
   799 		GETSHORT (port, pos);
       
   800 
       
   801 		len = dn_expand (srv, end, pos, name, 255);
       
   802 		if (pref < pref_prio) {
       
   803 			pref_prio = pref;
       
   804 			strcpy (pref_name, name);
       
   805 			pref_port = port;
       
   806 		}
       
   807 		pos += len;
       
   808 	}
       
   809 
       
   810 	if (pref_name[0]) {
       
   811 		*out_server = g_strdup (pref_name);
       
   812 		*out_port = pref_port;
       
   813 		return TRUE;
       
   814 	} */
       
   815 	return FALSE;
       
   816 }
       
   817 
       
   818 static void
       
   819 socket_close_io_channel (GIOChannel *io_channel)
       
   820 {
       
   821 	gint fd;
       
   822 
       
   823 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   824 	       "Freeing up IOChannel and file descriptor\n");
       
   825 
       
   826 	fd = g_io_channel_unix_get_fd (io_channel);
       
   827 
       
   828 	g_io_channel_unref (io_channel);
       
   829 
       
   830 	_lm_sock_close (fd);
       
   831 }
       
   832 
       
   833 static void
       
   834 _lm_socket_create_phase1 (LmSocket *socket, unsigned char *srv_ans, int len);
       
   835 static void
       
   836 _lm_socket_create_phase2 (LmSocket *socket, struct addrinfo *ans);
       
   837 
       
   838 #ifdef HAVE_ASYNCNS
       
   839 #define PHASE_1 0
       
   840 #define PHASE_2 1
       
   841 
       
   842 static gboolean
       
   843 _lm_socket_resolver_done (GSource *source,
       
   844     			  GIOCondition condition,
       
   845 			  gpointer data);
       
   846 
       
   847 
       
   848 static void
       
   849 _asyncns_done (LmSocket *socket)
       
   850 {
       
   851 	if (socket->resolv_channel != NULL) {
       
   852 		g_io_channel_unref (socket->resolv_channel);
       
   853 		socket->resolv_channel = NULL;
       
   854 	}
       
   855  
       
   856 	if (socket->watch_resolv) {
       
   857 		g_source_destroy(socket->watch_resolv);
       
   858 		socket->watch_resolv = NULL;
       
   859 	}
       
   860 
       
   861 	if (socket->asyncns_ctx) {
       
   862 		asyncns_free (socket->asyncns_ctx);
       
   863 		socket->asyncns_ctx = NULL;
       
   864 	}
       
   865 
       
   866  	socket->resolv_query = NULL;
       
   867 }
       
   868 
       
   869 void _asyncns_cancel (LmSocket *socket)
       
   870 {
       
   871 	if (socket == NULL)
       
   872 		return;
       
   873 
       
   874 	if (socket->asyncns_ctx) {
       
   875 		if (socket->resolv_query)
       
   876 			asyncns_cancel (socket->asyncns_ctx, socket->resolv_query);
       
   877 
       
   878 		_asyncns_done (socket);
       
   879 	}
       
   880 }
       
   881 
       
   882 static gboolean
       
   883 _asyncns_prep (LmSocket *socket, GError **error)
       
   884 {
       
   885 	if (socket->asyncns_ctx) {
       
   886 		return TRUE;
       
   887 	}
       
   888 
       
   889 	socket->asyncns_ctx = asyncns_new (1);
       
   890 	if (socket->asyncns_ctx == NULL) {
       
   891 		g_set_error (error,
       
   892 				LM_ERROR,                 
       
   893 				LM_ERROR_CONNECTION_FAILED,   
       
   894 				"can't initialise libasyncns");
       
   895 		return FALSE;
       
   896 	}
       
   897 
       
   898 	socket->resolv_channel =
       
   899 		g_io_channel_unix_new (asyncns_fd (socket->asyncns_ctx));
       
   900 
       
   901 	socket->watch_resolv = 
       
   902 		lm_misc_add_io_watch (socket->context,
       
   903 				      socket->resolv_channel,
       
   904 				      G_IO_IN,
       
   905 				      (GIOFunc) _lm_socket_resolver_done,
       
   906 				      socket);
       
   907 
       
   908 	return TRUE;
       
   909 }
       
   910 
       
   911 static gboolean
       
   912 _lm_socket_resolver_done (GSource *source,
       
   913     			  GIOCondition condition,
       
   914 			  gpointer data)
       
   915 {
       
   916 	LmSocket	*socket = lm_socket_ref ((LmSocket *) data);
       
   917 	struct addrinfo	*ans;
       
   918 	unsigned char   *srv_ans;
       
   919 	int 		 err;
       
   920 	gboolean         result = FALSE;
       
   921 
       
   922 	/* process pending data */
       
   923 	asyncns_wait (socket->asyncns_ctx, FALSE);
       
   924 
       
   925 	if (!asyncns_isdone (socket->asyncns_ctx, socket->resolv_query)) {
       
   926 		result = TRUE;
       
   927 	} else {
       
   928 		switch ((guint) asyncns_getuserdata (socket->asyncns_ctx, socket->resolv_query)) {
       
   929 		case PHASE_1:
       
   930 			err = asyncns_res_done (socket->asyncns_ctx, socket->resolv_query, &srv_ans);
       
   931 			socket->resolv_query = NULL;
       
   932 			_lm_socket_create_phase1 (socket, (err <= 0) ? NULL : srv_ans, err);
       
   933 			result = TRUE;
       
   934 			break;
       
   935 		case PHASE_2:
       
   936 			err = asyncns_getaddrinfo_done (socket->asyncns_ctx, socket->resolv_query, &ans);
       
   937 			socket->resolv_query = NULL;
       
   938 			_lm_socket_create_phase2 (socket, (err) ? NULL : ans);
       
   939 			_asyncns_done (socket);
       
   940 			break;
       
   941 		default:
       
   942 			g_assert_not_reached();
       
   943 			break;
       
   944 		}
       
   945 	}
       
   946 
       
   947 	lm_socket_unref(socket);
       
   948 	
       
   949 	return result;
       
   950 }
       
   951 
       
   952 #endif
       
   953 
       
   954 static void
       
   955 _lm_socket_create_phase1 (LmSocket *socket,
       
   956 			  unsigned char *srv_ans,
       
   957 			  int len)
       
   958 {
       
   959 	const char          *remote_addr;
       
   960 	LmConnectData       *data;
       
   961 	struct addrinfo      req;
       
   962 #ifndef HAVE_ASYNCNS
       
   963 	struct addrinfo *ans;
       
   964 	int              err;
       
   965 #endif
       
   966 
       
   967 	if (srv_ans != NULL) {
       
   968 		gchar    *new_server;
       
   969 		guint     new_port;
       
   970 		gboolean  result;
       
   971 		result = socket_parse_srv_response (srv_ans, len, 
       
   972 						    &new_server, 
       
   973 						    &new_port);
       
   974 		if (result == TRUE) {
       
   975 			g_free (socket->server);
       
   976 			socket->server = new_server;
       
   977 			socket->port = new_port;
       
   978 		}
       
   979 	}
       
   980 
       
   981 	/* If server wasn't specified and SRV failed, use domain */
       
   982 	if (!socket->server) {
       
   983 		lm_verbose ("SRV lookup failed, trying jid domain\n");
       
   984 		socket->server = g_strdup (socket->domain);
       
   985 	}
       
   986 
       
   987 	if (socket->proxy) {
       
   988 		remote_addr = lm_proxy_get_server (socket->proxy);
       
   989 	} else {
       
   990 		remote_addr = socket->server;
       
   991 	}
       
   992 
       
   993 	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   994 	       "Going to connect to %s%s:%u\n", (socket->proxy) ? "proxy " : "",
       
   995 	       remote_addr, socket->port);*/
       
   996 	lm_verbose( "[_lm_socket_create_phase1]: Going to connect to %s%s:%u\n", (socket->proxy) ? "proxy " : "",
       
   997 	       remote_addr, socket->port);
       
   998 
       
   999 	data = g_new0 (LmConnectData, 1);
       
  1000 
       
  1001 	data->socket        = socket;
       
  1002 	data->connection    = socket->connection;
       
  1003 	data->fd            = -1;
       
  1004 	socket->connect_data = data;
       
  1005 
       
  1006 	memset (&req, 0, sizeof(req));
       
  1007 	req.ai_family   = AF_UNSPEC;
       
  1008 	req.ai_socktype = SOCK_STREAM;
       
  1009 	req.ai_protocol = IPPROTO_TCP;
       
  1010 
       
  1011 #ifdef HAVE_ASYNCNS
       
  1012 	if (!_asyncns_prep (socket, NULL))
       
  1013 		return;
       
  1014 
       
  1015 	socket->resolv_query =
       
  1016 	  	asyncns_getaddrinfo (socket->asyncns_ctx,
       
  1017 		    		     remote_addr,
       
  1018 				     NULL,
       
  1019 				     &req);
       
  1020 
       
  1021 	asyncns_setuserdata (socket->asyncns_ctx,
       
  1022 			     socket->resolv_query,
       
  1023 			     (gpointer) PHASE_2);
       
  1024 #else
       
  1025 	err = getaddrinfo (remote_addr, NULL, &req, &ans);
       
  1026 	lm_verbose( "[_lm_socket_create_phase1]: after getaddrinfo : %u\n", err);
       
  1027 	_lm_socket_create_phase2 (socket, (err) ? NULL : ans);
       
  1028 	if (err != 0) {
       
  1029 		return;
       
  1030 	}
       
  1031 #endif
       
  1032 }
       
  1033 
       
  1034 static void
       
  1035 _lm_socket_create_phase2 (LmSocket *socket, struct addrinfo *ans)
       
  1036 {
       
  1037 	if (ans == NULL) {
       
  1038 		lm_verbose ("error while resolving, bailing out\n");
       
  1039 		if (socket->connect_func) {
       
  1040 			(socket->connect_func) (socket, FALSE, socket->user_data);
       
  1041 		}
       
  1042 		g_free (socket->connect_data);
       
  1043 		socket->connect_data = NULL;
       
  1044 		return;
       
  1045 	}
       
  1046 
       
  1047 	socket->connect_data->resolved_addrs = ans;
       
  1048 	socket->connect_data->current_addr   = ans;
       
  1049 
       
  1050 	socket_do_connect (socket->connect_data);
       
  1051 }
       
  1052 
       
  1053 LmSocket *
       
  1054 lm_socket_create (GMainContext      *context,
       
  1055 		  IncomingDataFunc   data_func,
       
  1056 		  SocketClosedFunc   closed_func,
       
  1057 		  ConnectResultFunc  connect_func,
       
  1058 		  gpointer           user_data,
       
  1059 		  LmConnection      *connection,
       
  1060 		  gboolean           blocking,
       
  1061 		  const gchar       *server,
       
  1062 		  const gchar       *domain,
       
  1063 		  guint              port, 
       
  1064 		  LmSSL             *ssl,
       
  1065 		  LmProxy           *proxy,
       
  1066 		  GError           **error)
       
  1067 {
       
  1068 	LmSocket        *socket;
       
  1069 
       
  1070 #ifndef HAVE_ASYNCNS
       
  1071 	unsigned char    srv_ans[SRV_LEN];
       
  1072 	int              len;
       
  1073 #endif
       
  1074 	lm_verbose ("[lm_socket_create]: inside..");
       
  1075 	
       
  1076 	g_return_val_if_fail (domain != NULL, NULL);
       
  1077 	g_return_val_if_fail ((port >= MIN_PORT && port <= MAX_PORT), NULL);
       
  1078 	g_return_val_if_fail (data_func != NULL, NULL);
       
  1079 	g_return_val_if_fail (closed_func != NULL, NULL);
       
  1080 	g_return_val_if_fail (connect_func != NULL, NULL);
       
  1081 
       
  1082 	
       
  1083 	socket = g_new0 (LmSocket, 1);
       
  1084 	lm_verbose ("[lm_socket_create]: after g_new0 ");
       
  1085 
       
  1086 	socket->ref_count = 1;
       
  1087 
       
  1088 	socket->connection = connection;
       
  1089 	socket->domain = g_strdup (domain);
       
  1090 	socket->server = g_strdup (server);
       
  1091 	socket->port = port;
       
  1092 	socket->cancel_open = FALSE;
       
  1093 	socket->ssl = ssl;
       
  1094 	socket->ssl_started = FALSE;
       
  1095 	socket->proxy = NULL;
       
  1096 	socket->blocking = blocking;
       
  1097 
       
  1098 	if (context) {
       
  1099 		socket->context = g_main_context_ref (context);
       
  1100 	}
       
  1101 
       
  1102 	if (proxy) {
       
  1103 		socket->proxy = lm_proxy_ref (proxy);
       
  1104 	}
       
  1105 
       
  1106 	if (!server) {
       
  1107 		/*char          *srv;
       
  1108 		srv = g_strdup_printf ("_xmpp-client._tcp.%s", socket->domain);
       
  1109 		lm_verbose ("Performing a SRV lookup for %s\n", srv);
       
  1110 
       
  1111 #ifdef HAVE_ASYNCNS
       
  1112 		if (!_asyncns_prep (socket, error))
       
  1113 			return NULL;
       
  1114 		
       
  1115 		socket->resolv_query =
       
  1116 			asyncns_res_query (socket->asyncns_ctx, srv, C_IN, T_SRV);
       
  1117 		asyncns_setuserdata (socket->asyncns_ctx, socket->resolv_query, (gpointer) PHASE_1);
       
  1118 #else
       
  1119 		res_init ();
       
  1120 
       
  1121 		len = res_query (srv, C_IN, T_SRV, srv_ans, SRV_LEN);
       
  1122 		_lm_socket_create_phase1 (socket, (len < 1) ? NULL : srv_ans, len);
       
  1123 		g_free (srv);
       
  1124 #endif*/
       
  1125 	} else {
       
  1126 		lm_verbose ("SRV lookup disabled for %s\n", socket->server);
       
  1127 		_lm_socket_create_phase1 (socket, NULL, 0);
       
  1128 	}
       
  1129 
       
  1130 	if (socket->connect_data == NULL) {
       
  1131 		/* Open failed synchronously, probably a DNS lookup problem */
       
  1132 		lm_socket_unref(socket);
       
  1133 		
       
  1134 		g_set_error (error,
       
  1135 			     LM_ERROR,                 
       
  1136 			     LM_ERROR_CONNECTION_FAILED,   
       
  1137 			     "Failed to resolve server");
       
  1138 		
       
  1139 		return NULL;
       
  1140 	}
       
  1141 		
       
  1142 
       
  1143 	/* If the connection fails synchronously, we don't want to call the
       
  1144 	 * connect_func to indicate an error, we return an error indication
       
  1145 	 * instead. So, we delay saving the functions until after we know
       
  1146 	 * we are going to return success.
       
  1147 	 */
       
  1148 	socket->data_func = data_func;
       
  1149 	socket->closed_func = closed_func;
       
  1150 	socket->connect_func = connect_func;
       
  1151 	socket->user_data = user_data;
       
  1152 	
       
  1153 	return socket;
       
  1154 }
       
  1155 
       
  1156 void
       
  1157 lm_socket_flush (LmSocket *socket)
       
  1158 {
       
  1159 	g_return_if_fail (socket != NULL);
       
  1160 	g_return_if_fail (socket->io_channel != NULL);
       
  1161 
       
  1162 	g_io_channel_flush (socket->io_channel, NULL);
       
  1163 }
       
  1164 
       
  1165 void
       
  1166 lm_socket_close (LmSocket *socket)
       
  1167 {
       
  1168 	LmConnectData *data;
       
  1169 	int ret = 0;
       
  1170 	g_return_if_fail (socket != NULL);
       
  1171 
       
  1172 	if (socket->watch_connect) {
       
  1173 		g_source_destroy (socket->watch_connect);
       
  1174 		socket->watch_connect = NULL;
       
  1175 	}
       
  1176 	
       
  1177 	_lm_sock_close(socket->fd);
       
  1178 	data = socket->connect_data;
       
  1179 	ret = errno; lm_verbose("\n\n[lm_socket_close]: The errno after close fd is: %d",ret);
       
  1180 	if (data) {
       
  1181 		freeaddrinfo (data->resolved_addrs);
       
  1182 		socket->connect_data = NULL;
       
  1183 		g_free (data);
       
  1184 	}
       
  1185 
       
  1186 	if (socket->io_channel) {
       
  1187 		if (socket->watch_in) {
       
  1188 			g_source_destroy (socket->watch_in);
       
  1189 			socket->watch_in = NULL;
       
  1190 		}
       
  1191 
       
  1192 		if (socket->watch_err) {
       
  1193 			g_source_destroy (socket->watch_err);
       
  1194 			socket->watch_err = NULL;
       
  1195 		}
       
  1196 
       
  1197 		if (socket->watch_hup) {
       
  1198 			g_source_destroy (socket->watch_hup);
       
  1199 			socket->watch_hup = NULL;
       
  1200 		}
       
  1201 
       
  1202 		if (socket->watch_out) {
       
  1203 			g_source_destroy (socket->watch_out);
       
  1204 			socket->watch_out = NULL;
       
  1205 		}
       
  1206 
       
  1207 		socket_close_io_channel (socket->io_channel);
       
  1208 
       
  1209 		socket->io_channel = NULL;
       
  1210 		socket->fd = -1;
       
  1211 	}
       
  1212 }
       
  1213 
       
  1214 gchar *
       
  1215 lm_socket_get_local_host (LmSocket *socket)
       
  1216 {
       
  1217 	return _lm_sock_get_local_host (socket->fd);
       
  1218 }
       
  1219 
       
  1220 LmSocket *
       
  1221 lm_socket_ref (LmSocket *socket)
       
  1222 {
       
  1223 	g_return_val_if_fail (socket != NULL, NULL);
       
  1224 
       
  1225 	socket->ref_count++;
       
  1226 
       
  1227 	return socket;
       
  1228 }
       
  1229 
       
  1230 void
       
  1231 lm_socket_unref (LmSocket *socket)
       
  1232 {
       
  1233 	g_return_if_fail (socket != NULL);
       
  1234 
       
  1235 	socket->ref_count--;
       
  1236 
       
  1237 	if (socket->ref_count <= 0) {
       
  1238 		socket_free (socket);
       
  1239 	}
       
  1240 }
       
  1241 
       
  1242 gboolean
       
  1243 lm_socket_set_keepalive (LmSocket *socket, int delay)
       
  1244 {
       
  1245 #ifdef USE_TCP_KEEPALIVES
       
  1246 	return _lm_sock_set_keepalive (socket->fd, delay);
       
  1247 #else
       
  1248 	return FALSE;
       
  1249 #endif /* USE_TCP_KEEPALIVES */
       
  1250 }
       
  1251