loudmouth/lm-socket.c
changeset 196 209bfa124066
parent 161 05ddf1d0440f
child 202 42d0b1ed1b96
equal deleted inserted replaced
195:c6ae0ebc7733 196:209bfa124066
    16  * License along with this program; if not, write to the
    16  * License along with this program; if not, write to the
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    18  * Boston, MA 02111-1307, USA.
    18  * Boston, MA 02111-1307, USA.
    19  */
    19  */
    20 
    20 
       
    21 #include <config.h>
       
    22 
       
    23 #include <string.h>
       
    24 
       
    25 #include "lm-debug.h"
       
    26 #include "lm-internals.h"
       
    27 #include "lm-misc.h"
       
    28 #include "lm-ssl.h"
       
    29 #include "lm-ssl-internals.h"
       
    30 #include "lm-proxy.h"
    21 #include "lm-socket.h"
    31 #include "lm-socket.h"
    22 
    32 #include "lm-sock.h"
    23 #ifndef G_OS_WIN32
    33 #include "lm-error.h"
    24 typedef int LmSock;
    34 
    25 #else  /* G_OS_WIN32 */
    35 #define IN_BUFFER_SIZE 1024
    26 typedef SOCKET LmSock;
    36 #define MIN_PORT 1
    27 #endif /* G_OS_WIN32 */
    37 #define MAX_PORT 65536
    28 
       
    29 /* FIXME: Integrate with the SSL stuff */
       
    30 
       
    31 /* FIXME: IO Buffering both in/out here? */
       
    32 
    38 
    33 struct _LmSocket {
    39 struct _LmSocket {
    34 	LmSock          sock;
    40 	LmConnection *connection;
    35 	GIOChannel     *io_channel;
    41 	GMainContext *context;
    36 	guint           io_watch;
    42 
    37 	/* FIXME: Add the rest */
    43 	gchar        *server;
    38 
    44 	guint         port;
    39 	LmSSL          *ssl;
    45 
    40 	
    46 	gboolean      blocking;
    41 	LmSocketFuncs   funcs;
    47 
    42 	
    48 	LmSSL        *ssl;
    43 	LmSocketState   state;
    49 	LmProxy      *proxy;
    44 
    50 
    45 	gboolean        is_blocking;
    51 	GIOChannel   *io_channel;
    46 	
    52 	GSource      *watch_in;
    47 	gint            ref;
    53 	GSource      *watch_err;
    48 };
    54 	GSource      *watch_hup;
    49 
    55 
    50 typedef void   (* SocketDNSCallback)  (LmSocket      *socket,
    56 	LmSocketT      fd;
    51 				       SocketDNSData *data,
    57 
    52 				       gboolean       success);
    58 	GSource      *watch_connect;
    53 
    59 
    54 typedef struct {
    60 	gboolean      cancel_open;
    55 	/* Used when socket tries to connect */
    61 	
    56 	struct addrinfo   *resolved_addrs;
    62 	GSource      *watch_out;
    57 	struct addrinfo   *current_addr;
    63 	GString      *out_buf;
    58 
    64 
    59 	/* -- Internal during DNS lookup -- */
    65 	LmConnectData *connect_data;
    60 	LmSocket          *socket;
    66 
    61 	gchar             *host;
    67 	IncomingDataFunc func;
    62 	SocketDNSCallback  callback;
    68 	gpointer         user_data;
    63 } SocketDNSData;
    69 
    64 
    70 	guint          ref_count;
    65 static LmSocket *  socket_create            (void);
    71 }; 
    66 static void        socket_free              (LmSocket          *socket);
    72 
    67 static gboolean    socket_channel_event     (GIOChannel        *source,
    73 static void         socket_free                 (LmSocket      *socket);
    68 					     GIOCondition       condition,
    74 static void         socket_do_connect        (LmConnectData *connect_data);
    69 					     LmSocket          *socket);
    75 static gboolean     socket_connect_cb       (GIOChannel    *source, 
    70 static void        socket_dns_lookup        (LmSocket          *socket,
    76 						 GIOCondition   condition,
    71 					     const gchar       *host,
    77 						 LmConnectData *connect_data);
    72 					     SocketDNSCallback  callback);
    78 static gboolean socket_in_event          (GIOChannel   *source,
    73 static SocketDNSData * socket_dns_data_new  (LmSocket          *socket,
    79 					      GIOCondition  condition,
    74 					     const gchar       *host,
    80 					      LmSocket     *socket);
    75 					     SocketDNSCallback  callbac);
    81 static gboolean socket_hup_event         (GIOChannel   *source,
    76 static void            socket_dns_data_free (SocketDNSData     *data);
    82 					      GIOCondition  condition,
    77 static void            socket_start_connect (LmSocket          *socket,
    83 					      LmSocket     *socket);
    78 					     SocketDNSData     *data,
    84 static gboolean
    79 					     gboolean           success);
    85 socket_buffered_write_cb (GIOChannel   *source, 
    80 
    86 			      GIOCondition  condition,
    81 static LmSocket *
    87 			      LmSocket     *socket);
    82 socket_create (void)
       
    83 {
       
    84 	LmSocket *socket;
       
    85 
       
    86 	socket = g_new0 (LmSocket, 1);
       
    87 	socket->ref_count = 1;
       
    88 	socket->is_blocking = FALSE;
       
    89 	socket->state = LM_SOCKET_STATE_CLOSED;
       
    90 	socket->ssl = NULL;
       
    91 	
       
    92 	return socket;
       
    93 }
       
    94 
    88 
    95 static void
    89 static void
    96 socket_free (LmSocket *socket)
    90 socket_free (LmSocket *socket)
    97 {
    91 {
    98 	/* FIXME: Free up the rest of the memory */
    92 	g_free (socket->server);
    99 
       
   100 	if (socket->io_channel) {
       
   101 		if (socket->io_watch != 0) {
       
   102 			g_source_destroy (g_main_context_find_source_by_id (socket->context),
       
   103 					  socket->io_watch);
       
   104 			socket->io_watch = 0;
       
   105 		}
       
   106 
       
   107 		g_io_channel_unref (socket->io_channel);
       
   108 		socket->io_channel = NULL;
       
   109 
       
   110 		socket->fd = -1;
       
   111 	}
       
   112 
    93 
   113 	if (socket->ssl) {
    94 	if (socket->ssl) {
   114 		_lm_ssl_unref (socket->ssl);
    95 		lm_ssl_unref (socket->ssl);
   115 	}
    96 	}
   116 
    97 
   117 	g_free (socket->host);
    98 	if (socket->proxy) {
       
    99 		lm_proxy_unref (socket->proxy);
       
   100 	}
       
   101 	
       
   102 	if (socket->out_buf) {
       
   103 		g_string_free (socket->out_buf, TRUE);
       
   104 	}
       
   105 
   118 	g_free (socket);
   106 	g_free (socket);
   119 }
   107 }
   120 
   108 
       
   109 gint
       
   110 lm_socket_do_write (LmSocket     *socket,
       
   111 		     const gchar  *buf,
       
   112 		     gint          len)
       
   113 {
       
   114 	gint b_written;
       
   115 
       
   116 	if (socket->ssl) {
       
   117 		b_written = _lm_ssl_send (socket->ssl, buf, len);
       
   118 	} else {
       
   119 		GIOStatus io_status = G_IO_STATUS_AGAIN;
       
   120 		gsize     bytes_written;
       
   121 
       
   122 		while (io_status == G_IO_STATUS_AGAIN) {
       
   123 			io_status = g_io_channel_write_chars (socket->io_channel, 
       
   124 							      buf, len, 
       
   125 							      &bytes_written,
       
   126 							      NULL);
       
   127 		}
       
   128 
       
   129 		b_written = bytes_written;
       
   130 
       
   131 		if (io_status != G_IO_STATUS_NORMAL) {
       
   132 			b_written = -1;
       
   133 		}
       
   134 	}
       
   135 
       
   136 	return b_written;
       
   137 }
       
   138 
   121 static gboolean
   139 static gboolean
   122 socket_channel_event (GIOChannel   *source,
   140 socket_in_event (GIOChannel   *source,
       
   141 		     GIOCondition  condition,
       
   142 		     LmSocket     *socket)
       
   143 {
       
   144 	gchar     buf[IN_BUFFER_SIZE];
       
   145 	gsize     bytes_read;
       
   146 	GIOStatus status;
       
   147        
       
   148 	if (!socket->io_channel) {
       
   149 		return FALSE;
       
   150 	}
       
   151 
       
   152 	if (socket->ssl) {
       
   153 		status = _lm_ssl_read (socket->ssl, 
       
   154 				       buf, IN_BUFFER_SIZE - 1, &bytes_read);
       
   155 	} else {
       
   156 		status = g_io_channel_read_chars (socket->io_channel,
       
   157 						  buf, IN_BUFFER_SIZE - 1,
       
   158 						  &bytes_read,
       
   159 						  NULL);
       
   160 	}
       
   161 
       
   162 	if (status != G_IO_STATUS_NORMAL || bytes_read < 0) {
       
   163 		gint reason;
       
   164 		
       
   165 		switch (status) {
       
   166 		case G_IO_STATUS_EOF:
       
   167 			reason = LM_DISCONNECT_REASON_HUP;
       
   168 			break;
       
   169 		case G_IO_STATUS_AGAIN:
       
   170 			return TRUE;
       
   171 			break;
       
   172 		case G_IO_STATUS_ERROR:
       
   173 			reason = LM_DISCONNECT_REASON_ERROR;
       
   174 			break;
       
   175 		default:
       
   176 			reason = LM_DISCONNECT_REASON_UNKNOWN;
       
   177 		}
       
   178 
       
   179 		_lm_connection_do_close (socket->connection);
       
   180 		_lm_connection_signal_disconnect (socket->connection, reason);
       
   181 		
       
   182 		return FALSE;
       
   183 	}
       
   184 
       
   185 	buf[bytes_read] = '\0';
       
   186 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "\nRECV [%d]:\n", 
       
   187 	       (int)bytes_read);
       
   188 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   189 	       "-----------------------------------\n");
       
   190 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "'%s'\n", buf);
       
   191  	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
       
   192 	       "-----------------------------------\n");
       
   193 
       
   194 	lm_verbose ("Read: %d chars\n", (int)bytes_read);
       
   195 
       
   196 	(socket->func) (socket, buf, socket->user_data);
       
   197 
       
   198 	return TRUE;
       
   199 }
       
   200 
       
   201 
       
   202 
       
   203 static gboolean
       
   204 socket_hup_event (GIOChannel   *source,
   123 		      GIOCondition  condition,
   205 		      GIOCondition  condition,
   124 		      LmSocket     *socket)
   206 		      LmSocket     *socket)
   125 {
   207 {
   126 	if (condition & G_IO_IN)  {
   208 	lm_verbose ("HUP event: %d->'%s'\n", 
   127 		socket_signal_read_available ();
   209 		    condition, lm_misc_io_condition_to_str (condition));
   128 	}
   210 
   129 	if (condition & G_IO_OUT) {
   211 	if (!socket->io_channel) {
   130 		socket_attempt_write ();
   212 		return FALSE;
   131 	}
   213 	}
   132 	if (condition & G_IO_ERR ||
   214 
   133 	    condition & G_IO_HUP) {
   215 	_lm_connection_do_close (socket->connection);
   134 		socket_disconnected ();
   216 	_lm_connection_signal_disconnect (socket->connection, 
   135 	}
   217 					  LM_DISCONNECT_REASON_HUP);
       
   218 	
       
   219 	return TRUE;
       
   220 }
       
   221 
       
   222 void
       
   223 _lm_socket_succeeded (LmConnectData *connect_data)
       
   224 {
       
   225 	LmSocket     *socket;
       
   226 	
       
   227 	socket = connect_data->socket;
       
   228 
       
   229 	if (socket->watch_connect) {
       
   230 		g_source_destroy (socket->watch_connect);
       
   231 		socket->watch_connect = NULL;
       
   232 	}
       
   233 
       
   234 	/* Need some way to report error/success */
       
   235 	if (socket->cancel_open) {
       
   236 		lm_verbose ("Cancelling connection...\n");
       
   237 		return;
       
   238 	}
       
   239 	
       
   240 	socket->fd = connect_data->fd;
       
   241 	socket->io_channel = connect_data->io_channel;
       
   242 
       
   243 	freeaddrinfo (connect_data->resolved_addrs);
       
   244 	socket->connect_data = NULL;
       
   245 	g_free (connect_data);
       
   246 
       
   247 	if (socket->ssl) {
       
   248 		GError *error = NULL;
       
   249 
       
   250 		lm_verbose ("Setting up SSL...\n");
       
   251 	
       
   252 #ifdef HAVE_GNUTLS
       
   253 		/* GNU TLS requires the socket to be blocking */
       
   254 		_lm_sock_set_blocking (socket->fd, TRUE);
       
   255 #endif
       
   256 
       
   257 		if (!_lm_ssl_begin (socket->ssl, socket->fd,
       
   258 				    socket->server,
       
   259 				    &error)) {
       
   260 			lm_verbose ("Could not begin SSL\n");
       
   261 				    
       
   262 			if (error) {
       
   263 				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   264 				       "%s\n", error->message);
       
   265 				g_error_free (error);
       
   266 			}
       
   267 
       
   268  			_lm_sock_shutdown (socket->fd);
       
   269  			_lm_sock_close (socket->fd);
       
   270 
       
   271 			_lm_connection_do_close (socket->connection);
       
   272 
       
   273 			return;
       
   274 		}
       
   275 	
       
   276 #ifdef HAVE_GNUTLS
       
   277 		_lm_sock_set_blocking (socket->fd, FALSE); 
       
   278 #endif
       
   279 	}
       
   280 
       
   281 	socket->watch_in = 
       
   282 		lm_misc_add_io_watch (socket->context,
       
   283 				      socket->io_channel,
       
   284 				      G_IO_IN,
       
   285 				      (GIOFunc) socket_in_event,
       
   286 				      socket);
       
   287 
       
   288 	/* FIXME: if we add these, we don't get ANY
       
   289 	 * response from the server, this is to do with the way that
       
   290 	 * windows handles watches, see bug #331214.
       
   291 	 */
       
   292 #ifndef G_OS_WIN32
       
   293 	socket->watch_err = 
       
   294 		lm_misc_add_io_watch (socket->context,
       
   295 				      socket->io_channel,
       
   296 				      G_IO_ERR,
       
   297 				      (GIOFunc) _lm_connection_error_event,
       
   298 				      socket);
       
   299 		
       
   300 	socket->watch_hup =
       
   301 		lm_misc_add_io_watch (socket->context,
       
   302 				      socket->io_channel,
       
   303 				      G_IO_HUP,
       
   304 				      (GIOFunc) socket_hup_event,
       
   305 				      socket);
       
   306 #endif
       
   307 
       
   308 	_lm_connection_socket_result (socket->connection, TRUE);
       
   309 }
       
   310 
       
   311 void 
       
   312 _lm_socket_failed_with_error (LmConnectData *connect_data, int error) 
       
   313 {
       
   314 	LmSocket *socket;
       
   315 	
       
   316 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   317 	       "Connection failed: %s (error %d)\n",
       
   318 	       _lm_sock_get_error_str (error), error);
       
   319 	
       
   320 	socket = connect_data->socket;
       
   321 
       
   322 	connect_data->current_addr = connect_data->current_addr->ai_next;
       
   323 	
       
   324 	if (socket->watch_connect) {
       
   325 		g_source_destroy (socket->watch_connect);
       
   326 		socket->watch_connect = NULL;
       
   327 	}
       
   328 
       
   329 	if (connect_data->io_channel != NULL) {
       
   330 		g_io_channel_unref (connect_data->io_channel);
       
   331 		/* FIXME: need to check for last unref and close the socket */
       
   332 	}
       
   333 	
       
   334 	if (connect_data->current_addr == NULL) {
       
   335 		_lm_connection_socket_result (socket->connection, FALSE);
       
   336 		
       
   337 		freeaddrinfo (connect_data->resolved_addrs);
       
   338 		socket->connect_data = NULL;
       
   339 		g_free (connect_data);
       
   340 	} else {
       
   341 		/* try to connect to the next host */
       
   342 		socket_do_connect (connect_data);
       
   343 	}
       
   344 }
       
   345 
       
   346 void 
       
   347 _lm_socket_failed (LmConnectData *connect_data)
       
   348 {
       
   349 	_lm_socket_failed_with_error (connect_data, _lm_sock_get_last_error());
       
   350 }
       
   351 
       
   352 static gboolean 
       
   353 socket_connect_cb (GIOChannel   *source, 
       
   354 		       GIOCondition  condition,
       
   355 		       LmConnectData *connect_data) 
       
   356 {
       
   357 	LmSocket        *socket;
       
   358 	struct addrinfo *addr;
       
   359 	int              err;
       
   360 	socklen_t        len;
       
   361 	LmSocketT         fd; 
       
   362 
       
   363 	socket = connect_data->socket;
       
   364 	addr = connect_data->current_addr;
       
   365 	fd = g_io_channel_unix_get_fd (source);
       
   366 
       
   367 	if (condition == G_IO_ERR) {
       
   368 		len = sizeof (err);
       
   369 		_lm_sock_get_error (fd, &err, &len);
       
   370 		if (!_lm_sock_is_blocking_error (err)) {
       
   371 			g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   372 			       "Connection failed.\n");
       
   373 
       
   374 			_lm_socket_failed_with_error (connect_data, err);
       
   375 
       
   376 			socket->watch_connect = NULL;
       
   377 			return FALSE;
       
   378 		}
       
   379 	}
       
   380 
       
   381 	if (_lm_connection_async_connect_waiting (socket->connection)) {
       
   382 		gint res;
       
   383 
       
   384 		fd = g_io_channel_unix_get_fd (source);
       
   385 
       
   386 		res = _lm_sock_connect (fd, addr->ai_addr, (int)addr->ai_addrlen);  
       
   387 		if (res < 0) {
       
   388 			err = _lm_sock_get_last_error ();
       
   389 			if (_lm_sock_is_blocking_success (err)) {
       
   390 				_lm_connection_set_async_connect_waiting (socket->connection, FALSE);
       
   391 
       
   392 				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   393 				       "Connection success (1).\n");
       
   394 				
       
   395 				_lm_socket_succeeded (connect_data);
       
   396 			}
       
   397 			
       
   398 			if (_lm_connection_async_connect_waiting (socket->connection) &&
       
   399 			    !_lm_sock_is_blocking_error (err)) {
       
   400 				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   401 				       "Connection failed.\n");
       
   402 
       
   403 				_lm_sock_close (connect_data->fd);
       
   404 				_lm_socket_failed_with_error (connect_data, err);
       
   405 
       
   406 				socket->watch_connect = NULL;
       
   407 				return FALSE;
       
   408 			}
       
   409 		} 
       
   410 	} else {		
       
   411 		/* for blocking sockets, G_IO_OUT means we are connected */
       
   412 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   413 		       "Connection success (2).\n");
       
   414 		
       
   415 		_lm_socket_succeeded (connect_data);
       
   416 	}
       
   417  	return TRUE; 
   136 }
   418 }
   137 
   419 
   138 static void
   420 static void
   139 socket_dns_lookup (LmSocket          *socket,
   421 socket_do_connect (LmConnectData *connect_data) 
   140 		   const gchar       *host,
   422 {
   141 		   SocketDNSCallback  callback);
   423 	LmSocket        *socket;
   142 {
   424 	LmSocketT        fd;
   143 	SocketDNSData   *data;
   425 	int              res, err;
   144 	struct addrinfo  req;
       
   145 	struct addrinfo  ans;
       
   146 	int              err;
       
   147 
       
   148 	/* FIXME: This should not be synchronous */
       
   149 	data = socket_dns_data_new (socket, host, callback);
       
   150 
       
   151 	memset (&req, 0, sizeof (req));
       
   152 	req.ai_family   = AF_UNSPEC;
       
   153 	req.ai_socktype = SOCK_STREAM;
       
   154 	req.ai_protocol = IPPROTO_TCP;
       
   155 
       
   156 	err = getaddrinfo (data->host, NULL, &req, &ans);
       
   157 	if (err != 0) {
       
   158 		/* FIXME: Handle error */
       
   159 		data->callback (data->socket, data, FALSE);
       
   160 	}
       
   161 
       
   162 	data->resolved_addrs = ans;
       
   163 	data->current_addr   = ans;
       
   164 
       
   165 	data->callback (data->socket, data, TRUE);
       
   166 }
       
   167 
       
   168 static SocketDNSData *
       
   169 socket_dns_data_new (LmSocket          *socket,
       
   170 		     const gchar       *host,
       
   171 		     SocketDNSCallback  callbac)
       
   172 {
       
   173 	SocketDNSData *data;
       
   174 
       
   175 	data = g_new0 (SocketDNSData, 1);
       
   176 	
       
   177 	data->socket   = lm_socket_ref (socket);
       
   178 	data->host     = g_strdup (host);
       
   179 	data->callback = callback;
       
   180 
       
   181 	data->resolved_addrs = data->current_addr = NULL;
       
   182 
       
   183 	return data;
       
   184 }
       
   185 
       
   186 static void
       
   187 socket_dns_data_free (SocketDNSData *data)
       
   188 {
       
   189 	lm_socket_unref (data->socket);
       
   190 	g_free (data->host);
       
   191 
       
   192 	if (data->resolved_addrs) {
       
   193 		freeaddrinfo (data->resolved_addrs);;
       
   194 		deta->resolved_addrs = NULL;
       
   195 	}
       
   196 
       
   197 	g_free (data);
       
   198 }
       
   199 
       
   200 static void
       
   201 socket_start_connect (LmSocket      *socket,
       
   202 		      SocketDNSData *data,
       
   203 		      gboolean       success)
       
   204 {
       
   205 	struct addrinfo *addr;
       
   206 	int              port;
   426 	int              port;
   207 	char             name[NI_MAXHOST];
   427 	char             name[NI_MAXHOST];
   208 	char             portname[NI_MAXSERV];
   428 	char             portname[NI_MAXSERV];
   209 	gint             fd;
   429 	struct addrinfo *addr;
   210 
   430 	
   211 	if (!success) {
   431 	socket = connect_data->socket;
   212 		socket_dns_data_free (data);
   432 	addr = connect_data->current_addr;
   213 		/* FIXME: Report error */
   433  
   214 		return;
       
   215 	}
       
   216 
       
   217 	addr = data->current_addr;
       
   218 
       
   219 	if (socket->proxy) {
   434 	if (socket->proxy) {
   220 		port = htons (lm_proxy_get_port (socket->proxy));
   435 		port = htons (lm_proxy_get_port (socket->proxy));
   221 	} else {
   436 	} else {
   222 		port = htons (socket->port);
   437 		port = htons (socket->port);
   223 	}
   438 	}
   224 
   439 	
   225 	((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
   440 	((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
   226 
   441 
   227 	res = getnameinfo (addr->ai_addr,
   442 	res = getnameinfo (addr->ai_addr,
   228 			   (socklen_t) addr->ai_addrlen,
   443 			   (socklen_t)addr->ai_addrlen,
   229 			   name, sizeof (name),
   444 			   name,     sizeof (name),
   230 			   portname, sizeof (portname),
   445 			   portname, sizeof (portname),
   231 			   NI_NUMERICHOST | NI_NUMERICSERV);
   446 			   NI_NUMERICHOST | NI_NUMERICSERV);
   232 
   447 	
   233 	if (res < 0) {
   448 	if (res < 0) {
   234 		/* FIXME: Report failure */
   449 		_lm_socket_failed (connect_data);
   235 		return;
   450 		return;
   236 	}
   451 	}
   237 
   452 
       
   453 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   454 	       "Trying %s port %s...\n", name, portname);
       
   455 	
   238 	fd = _lm_sock_makesocket (addr->ai_family,
   456 	fd = _lm_sock_makesocket (addr->ai_family,
   239 				  addr->ai_socktype,
   457 				  addr->ai_socktype, 
   240 				  addr->ai_protocol);
   458 				  addr->ai_protocol);
   241 
   459 	
   242 	if (!_LM_SOCK_VALID (fd)) {
   460 	if (!_LM_SOCK_VALID (fd)) {
   243 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
   461 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
   244 		       "Failed making socket, error:%d...\n",
   462 		       "Failed making socket, error:%d...\n",
   245 		       _lm_sock_get_last_error ());
   463 		       _lm_sock_get_last_error ());
   246 
   464 
   247 		/* FIXME: Report failure */
   465 		_lm_socket_failed (connect_data);
       
   466 
   248 		return;
   467 		return;
   249 	}
   468 	}
   250 
   469 
   251 	/* Even though it says _unix_new(), it is supported by glib on
   470 	/* Even though it says _unix_new(), it is supported by glib on
   252 	 * win32 because glib does some cool stuff to find out if it
   471 	 * win32 because glib does some cool stuff to find out if it
   253 	 * can treat it as a FD or a windows SOCKET.
   472 	 * can treat it as a FD or a windows SOCKET.
   254 	 */
   473 	 */
   255 	socket->fd = fd;
   474 	connect_data->fd = fd;
   256 	socket->io_channel = g_io_channel_unix_new (fd);
   475 	connect_data->io_channel = g_io_channel_unix_new (fd);
   257 
   476 	
   258 	g_io_channel_set_encoding (connect_data->io_channel, NULL, NULL);
   477 	g_io_channel_set_encoding (connect_data->io_channel, NULL, NULL);
   259 	g_io_channel_set_buffered (connect_data->io_channel, FALSE);
   478 	g_io_channel_set_buffered (connect_data->io_channel, FALSE);
   260 
   479 
   261 	_lm_sock_set_blocking (socket->fd, FALSE);
   480 	_lm_sock_set_blocking (connect_data->fd, socket->blocking);
   262 
   481 	
   263 	if (socket->proxy) {
   482 	if (socket->proxy) {
   264 		socket->io_watch_connect =
   483 		socket->watch_connect =
   265 			socket_add_watch (socket,
   484 			lm_misc_add_io_watch (socket->context,
   266 					  socket->io_channel,
   485 					      connect_data->io_channel,
   267 					  G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP,
   486 					      G_IO_OUT|G_IO_ERR,
   268 					  (GIOFunc) _lm_proxy_connect_cb, 
   487 					      (GIOFunc) _lm_proxy_connect_cb, 
   269 					  socket);
   488 					      connect_data);
   270 	} else {
   489 	} else {
   271 		socket->io_watch_connect =
   490 		socket->watch_connect =
   272 			socket_add_watch (socket,
   491 			lm_misc_add_io_watch (socket->context,
   273 					  socket->io_channel,
   492 					      connect_data->io_channel,
   274 					  G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP, 
   493 					      G_IO_OUT|G_IO_ERR,
   275 					  (GIOFunc) socket_connect_cb,
   494 					      (GIOFunc) socket_connect_cb,
   276 					  socket);
   495 					      connect_data);
   277 	}
   496 	}
   278 	
   497 
   279 	/* FIXME: Continue and connect */
   498 	_lm_connection_set_async_connect_waiting (socket->connection, !socket->blocking);
       
   499 
       
   500   	res = _lm_sock_connect (connect_data->fd, 
       
   501 				addr->ai_addr, (int)addr->ai_addrlen);  
       
   502 	if (res < 0) {
       
   503 		err = _lm_sock_get_last_error ();
       
   504 		if (!_lm_sock_is_blocking_error (err)) {
       
   505 			_lm_sock_close (connect_data->fd);
       
   506 			_lm_socket_failed_with_error (connect_data, err);
       
   507 
       
   508 			return;
       
   509 		}
       
   510 	}
       
   511 }
       
   512 
       
   513 gboolean
       
   514 lm_socket_output_is_buffered (LmSocket     *socket,
       
   515 			       const gchar  *buffer,
       
   516 			       gint          len)
       
   517 {
       
   518 	if (socket->out_buf) {
       
   519 		lm_verbose ("Appending %d bytes to output buffer\n", len);
       
   520 		g_string_append_len (socket->out_buf, buffer, len);
       
   521 		return TRUE;
       
   522 	}
       
   523 
       
   524 	return FALSE;
       
   525 }
       
   526 
       
   527 void
       
   528 lm_socket_setup_output_buffer (LmSocket     *socket,
       
   529 				const gchar  *buffer,
       
   530 				gint          len)
       
   531 {
       
   532 	lm_verbose ("OUTPUT BUFFER ENABLED\n");
       
   533 
       
   534 	socket->out_buf = g_string_new_len (buffer, len);
       
   535 
       
   536 	socket->watch_out =
       
   537 		lm_misc_add_io_watch (socket->context,
       
   538 				      socket->io_channel,
       
   539 				      G_IO_OUT,
       
   540 				      (GIOFunc) socket_buffered_write_cb,
       
   541 				      socket);
       
   542 }
       
   543 
       
   544 static gboolean
       
   545 socket_buffered_write_cb (GIOChannel   *source, 
       
   546 			      GIOCondition  condition,
       
   547 			      LmSocket     *socket)
       
   548 {
       
   549 	gint     b_written;
       
   550 	GString *out_buf;
       
   551 	/* FIXME: Do the writing */
       
   552 
       
   553 	out_buf = socket->out_buf;
       
   554 	if (!out_buf) {
       
   555 		/* Should not be possible */
       
   556 		return FALSE;
       
   557 	}
       
   558 
       
   559 	b_written = lm_socket_do_write (socket, out_buf->str, out_buf->len);
       
   560 
       
   561 	if (b_written < 0) {
       
   562 		_lm_connection_error_event (socket,
       
   563 					    G_IO_HUP, socket->connection);
       
   564 		return FALSE;
       
   565 	}
       
   566 
       
   567 	g_string_erase (out_buf, 0, (gsize) b_written);
       
   568 	if (out_buf->len == 0) {
       
   569 		lm_verbose ("Output buffer is empty, going back to normal output\n");
       
   570 
       
   571 		if (socket->watch_out) {
       
   572 			g_source_destroy (socket->watch_out);
       
   573 			socket->watch_out = NULL;
       
   574 		}
       
   575 
       
   576 		g_string_free (out_buf, TRUE);
       
   577 		socket->out_buf = NULL;
       
   578 		return FALSE;
       
   579 	}
       
   580 
       
   581 	return TRUE;
   280 }
   582 }
   281 
   583 
   282 LmSocket *
   584 LmSocket *
   283 lm_socket_new (LmSocketFuncs funcs, const gchar *host, guint port)
   585 lm_socket_create (GMainContext      *context,
   284 {
   586 		  IncomingDataFunc   func,
   285 	LmSocket *socket;
   587 		  gpointer           user_data,
   286 
   588 		  LmConnection      *connection,
   287 	socket = socket_create ();
   589 		  gboolean           blocking,
   288 
   590 		  const gchar       *server,
   289 	socket->funcs = funcs;
   591 		  guint              port, 
   290 	socket->host = g_strdup (host);
   592 		  LmSSL             *ssl,
       
   593 		  LmProxy           *proxy,
       
   594 		  GError           **error)
       
   595 {
       
   596 	LmSocket        *socket;
       
   597 	struct addrinfo  req;
       
   598 	struct addrinfo *ans;
       
   599 	LmConnectData   *data;
       
   600 
       
   601 	g_return_val_if_fail (server != NULL, NULL);
       
   602 	g_return_val_if_fail ((port >= MIN_PORT && port <= MAX_PORT), NULL);
       
   603 	g_return_val_if_fail (func != NULL, NULL);
       
   604 
       
   605 	socket = g_new0 (LmSocket, 1);
       
   606 
       
   607 	memset (&req, 0, sizeof(req));
       
   608 
       
   609 	req.ai_family   = AF_UNSPEC;
       
   610 	req.ai_socktype = SOCK_STREAM;
       
   611 	req.ai_protocol = IPPROTO_TCP;
       
   612 
       
   613 	socket->ref_count = 1;
       
   614 
       
   615 	socket->connection = connection;
       
   616 	socket->server = g_strdup (server);
   291 	socket->port = port;
   617 	socket->port = port;
   292 	socket->is_blocking = FALSE;
   618 	socket->cancel_open = FALSE;
       
   619 	socket->ssl = NULL;
       
   620 	socket->proxy = NULL;
       
   621 	socket->blocking = blocking;
       
   622 	socket->func = func;
       
   623 	socket->user_data = user_data;
       
   624 
       
   625 	if (context) {
       
   626 		socket->context = g_main_context_ref (context);
       
   627 	}
       
   628 
       
   629 	if (proxy) {
       
   630 		int          err;
       
   631 		const gchar *proxy_server;
       
   632 
       
   633 		socket->proxy = lm_proxy_ref (proxy);
       
   634 
       
   635 		proxy_server = lm_proxy_get_server (socket->proxy);
       
   636 
       
   637 		/* Connect through proxy */
       
   638 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   639 		       "Going to connect to proxy %s\n", proxy_server);
       
   640 
       
   641 		err = getaddrinfo (proxy_server, NULL, &req, &ans);
       
   642 		if (err != 0) {
       
   643 			const char *str;
       
   644 
       
   645 			str = _lm_sock_addrinfo_get_error_str (err);
       
   646 			g_set_error (error,
       
   647 				     LM_ERROR,                 
       
   648 				     LM_ERROR_CONNECTION_FAILED,   
       
   649 				     str);
       
   650 			return NULL;
       
   651 		}
       
   652 	} else { 
       
   653 		int err;
       
   654 
       
   655 		/* Connect directly */
       
   656 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
       
   657 		       "Going to connect to %s\n", 
       
   658 		       socket->server);
       
   659 
       
   660 		err = getaddrinfo (socket->server, 
       
   661 				   NULL, &req, &ans);
       
   662 		if (err != 0) {
       
   663 			const char *str;
       
   664 
       
   665 			str = _lm_sock_addrinfo_get_error_str (err);
       
   666 			g_set_error (error,
       
   667 				     LM_ERROR,                 
       
   668 				     LM_ERROR_CONNECTION_FAILED,   
       
   669 				     str);
       
   670 			return NULL;
       
   671 		}
       
   672 	}
       
   673 
       
   674 	if (ssl) {
       
   675 		socket->ssl = lm_ssl_ref (ssl);
       
   676 		_lm_ssl_initialize (socket->ssl);
       
   677 	}
       
   678 
       
   679 	/* Prepare and do the nonblocking connection */
       
   680 	data = g_new (LmConnectData, 1);
       
   681 
       
   682 	data->socket         = socket;
       
   683 	data->connection     = connection;
       
   684 	data->resolved_addrs = ans;
       
   685 	data->current_addr   = ans;
       
   686 	data->io_channel     = NULL;
       
   687 	data->fd             = -1;
       
   688 
       
   689 	socket->connect_data = data;
       
   690 
       
   691 	socket_do_connect (data);
   293 
   692 
   294 	return socket;
   693 	return socket;
   295 }
   694 }
   296 
   695 
   297 void
   696 void
   298 lm_socket_open (LmSocket *socket)
   697 lm_socket_flush (LmSocket *socket)
   299 {
   698 {
   300 	g_return_if_fail (socket != NULL);
   699 	g_return_if_fail (socket != NULL);
   301 
   700 	g_return_if_fail (socket->io_channel != NULL);
   302 	socket_dns_lookup (socket, socket->host, socket_start_connect);
   701 
   303 }
   702 	g_io_channel_flush (socket->io_channel, NULL);
   304 
       
   305 int
       
   306 lm_socket_get_fd (LmSocket *socket)
       
   307 {
       
   308 	g_return_val_if_fail (socket != NULL, -1);
       
   309 
       
   310 	return socket->fd;
       
   311 }
       
   312 
       
   313 gboolean
       
   314 lm_socket_get_is_blocking (LmSocket *socket)
       
   315 {
       
   316 	return socket->is_blocking;
       
   317 }
   703 }
   318 
   704 
   319 void
   705 void
   320 lm_socket_set_is_blocking (LmSocket *socket, gboolean is_block)
   706 lm_socket_close (LmSocket *socket)
   321 {
   707 {
   322 	int res;
   708 	LmConnectData *data;
   323 
   709 
   324 	g_return_if_fail (socket != NULL);
   710 	if (socket->watch_connect) {
   325 
   711 		g_source_destroy (socket->watch_connect);
   326 	/* FIXME: Don't unset all flags */
   712 		socket->watch_connect = NULL;
   327 
   713 	}
   328 #ifndef G_OS_WIN32
   714 	
   329 	res = fcntl (socket->sock, F_SETFL, is_block ? 0 : O_NONBLOCK);
   715 	data = socket->connect_data;
   330 #else  /* G_OS_WIN32 */
   716 	if (data) {
   331 	u_long mode = (is_block ? 0 : 1);
   717 		freeaddrinfo (data->resolved_addrs);
   332 	res = ioctlsocket (socket->sock, FIONBIO, &mode);
   718 		socket->connect_data = NULL;
   333 #endif /* G_OS_WIN32 */
   719 		g_free (data);
   334 
   720 	}
   335 	if (res != 0) {
   721 
   336 		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
   722 	if (socket->io_channel) {
   337 		       "Could not set socket to be %s\n",
   723 		if (socket->watch_in) {
   338 		       block ? "blocking" : "non-blocking");
   724 			g_source_destroy (socket->watch_in);
   339 	}
   725 			socket->watch_in = NULL;
   340 
   726 		}
   341 	socket->is_blocking = is_block;
   727 
   342 }
   728 		if (socket->watch_err) {
   343 
   729 			g_source_destroy (socket->watch_err);
   344 int
   730 			socket->watch_err = NULL;
   345 lm_socket_write (LmSocket   *socket,
   731 		}
   346 		 gsize       size,
   732 
   347 		 gchar      *buf,
   733 		if (socket->watch_hup) {
   348 		 GError    **error)
   734 			g_source_destroy (socket->watch_hup);
   349 {
   735 			socket->watch_hup = NULL;
   350 	gint b_written;
   736 		}
   351 	
   737 
   352 	g_return_val_if_fail (socket != NULL, -1);
   738 		if (socket->watch_out) {
   353 
   739 			g_source_destroy (socket->watch_out);
   354 	if (socket->ssl) {
   740 			socket->watch_out = NULL;
   355 		b_written = _lm_ssl_send (socket->ssl, buf, len);
   741 		}
   356 	} else {
   742 
   357 		GIOStatus io_status = G_IO_STATUS_AGAIN;
   743 		g_io_channel_unref (socket->io_channel);
   358 		gsize     bytes_written = 0;
   744 		socket->io_channel = NULL;
   359 
   745 
   360 		while (io_status == G_IO_STATUS_AGAIN) {
   746 		socket->fd = -1;
   361 			io_status = g_io_channel_write_chars (socket->io_channel,
   747 	}
   362 							      buf, size,
       
   363 							      &bytes_written,
       
   364 							      NULL);
       
   365 		}
       
   366 
       
   367 		b_written = bytes_written;
       
   368 
       
   369 		if (io_status != G_IO_STATUS_NORMAL) {
       
   370 			b_written = -1;
       
   371 		}
       
   372 	}
       
   373 
       
   374 	return b_written;
       
   375 }
       
   376 
       
   377 int
       
   378 lm_socket_read (LmSocket   *socket,
       
   379 		gsize       size,
       
   380 		gchar      *buf,
       
   381 		GError    **error)
       
   382 {
       
   383 	gsize     bytes_read = 0;
       
   384 	GIOStatus status =  G_IO_STATUS_AGAIN;
       
   385 
       
   386 	g_return_val_if_fail (socket != NULL, -1);
       
   387 
       
   388 	while (status == G_IO_STATUS_AGAIN) {
       
   389 		if (socket->ssl) {
       
   390 			status = _lm_ssl_read (socket->ssl, 
       
   391 					       buf, size, &bytes_read);
       
   392 		} else {
       
   393 			status = g_io_channel_read_chars (socket->io_channel, 
       
   394 							  buf, size, 
       
   395 							  &bytes_read,
       
   396 							  NULL);
       
   397 		}
       
   398 	}
       
   399 
       
   400 	if (status != G_IO_STATUS_NORMAL || bytes_read < 0) {
       
   401 		/* FIXME: Set error */
       
   402 
       
   403 		return -1;
       
   404 	}
       
   405 
       
   406 	return bytes_read;
       
   407 }
       
   408 
       
   409 gboolean
       
   410 lm_socket_close (LmSocket *socket, GError **error)
       
   411 {
       
   412 #ifndef G_OS_WIN32
       
   413 	close (socket->sock);
       
   414 #else /* G_OS_WIN32 */
       
   415 	closesocket (socket->sock);
       
   416 #endif /* G_OS_WIN32 */
       
   417 }
   748 }
   418 
   749 
   419 LmSocket *
   750 LmSocket *
   420 lm_socket_ref (LmSocket *socket)
   751 lm_socket_ref (LmSocket *socket)
   421 {
   752 {
   422 	g_return_val_if_fail (socket != NULL, NULL);
   753 	g_return_val_if_fail (socket != NULL, NULL);
   423 
   754 
   424 	socket->ref++;
   755 	socket->ref_count++;
   425 	
   756 
   426 	return socket;
   757 	return socket;
   427 }
   758 }
   428 
   759 
   429 void
   760 void
   430 lm_socket_unref (LmSocket *socket)
   761 lm_socket_unref (LmSocket *socket)
   431 {
   762 {
   432 	g_return_if_fail (socket != NULL);
   763 	g_return_if_fail (socket != NULL);
   433 	
   764 
   434 	socket->ref--;
   765 	socket->ref_count--;
   435 	
   766 
   436 	if (socket->ref <= 0) {
   767 	if (socket->ref_count <= 0) {
   437 		socket_free (socket);
   768 		socket_free (socket);
   438 	}
   769 	}
   439 }
   770 }
   440 
   771