示例#1
0
static int remote_connect(const char* host, unsigned port,
		void** connectiondata) {
	g_message("connecting to remote: %s on port %u", host, port);

	GSocket* sock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
			G_SOCKET_PROTOCOL_TCP, NULL);

	GSocketConnectable* addr = g_network_address_new(host, port);
	GSocketAddressEnumerator* enumerator = g_socket_connectable_enumerate(addr);

	int ret = EMCUETITI_PORT_REMOTE_TRYAGAIN;

	GSocketAddress* sockaddr;
	while ((sockaddr = g_socket_address_enumerator_next(enumerator, NULL, NULL))) {
		g_message("connecting...");
		GError* error = NULL;
		if (g_socket_connect(sock, sockaddr, NULL, &error)) {
			g_message("connected");
			g_socket_set_blocking(sock, FALSE);
			remote_wireupsocketcallback(sock);
			*connectiondata = sock;
			ret = EMCUETITI_PORT_REMOTE_OK;
			break;
		} else {
			g_message("failed to connect %d:%s", error->code, error->message);
		}
	}

	if (ret != EMCUETITI_PORT_REMOTE_OK)
		g_object_unref(sock);

	g_object_unref(addr);
	g_object_unref(enumerator);
	return ret;
}
示例#2
0
/* TODO: could use dbus, but for portability maybe not..... */
static void
do_connect(SpiceVDAgent *agent)
{
    GError *error = NULL;
    GSocketAddressEnumerator *enumerator;
    GSocketAddress *address;

#ifdef G_OS_UNIX
    agent->socket = g_socket_new(G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, 0, &error);
    agent->connectable = G_SOCKET_CONNECTABLE(g_unix_socket_address_new(vdagentd_socket));
#endif

    enumerator = g_socket_connectable_enumerate (agent->connectable);
    while (TRUE) {
        address = g_socket_address_enumerator_next (enumerator, agent->cancellable, NULL);
        if (!address) {
            g_error("can't connect to socket");
            exit(1);
        }

        if (g_socket_connect(agent->socket, address, agent->cancellable, &error))
            break;

        g_debug("Connection failed, trying next");
        g_clear_error (&error);
        g_object_unref (address);
    }
    g_object_unref(enumerator);

    agent->connection =
        G_IO_STREAM(g_socket_connection_factory_create_connection(agent->socket));
    g_debug("Connected to %s %p", vdagentd_socket, agent->connection);

    send_xorg_config(agent);
}
示例#3
0
gboolean
xdmcp_client_start (XDMCPClient *client)
{
    if (client->priv->socket)
        return TRUE;

    g_autoptr(GError) error = NULL;
    client->priv->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
    if (error)
        g_warning ("Error creating XDMCP socket: %s", error->message);
    if (!client->priv->socket)
        return FALSE;

    GSocketConnectable *address = g_network_address_new (client->priv->host, client->priv->port);
    GSocketAddressEnumerator *enumerator = g_socket_connectable_enumerate (address);
    while (TRUE)
    {
        g_autoptr(GError) e = NULL;
        g_autoptr(GSocketAddress) socket_address = g_socket_address_enumerator_next (enumerator, NULL, &e);
        if (e)
            g_warning ("Failed to get socket address: %s", e->message);
        if (!socket_address)
            return FALSE;

        if (!g_socket_connect (client->priv->socket, socket_address, NULL, &e))
        {
            g_warning ("Unable to connect XDMCP socket: %s", error->message);
            continue;
        }

        g_io_add_watch (g_io_channel_unix_new (g_socket_get_fd (client->priv->socket)), G_IO_IN, xdmcp_data_cb, client);

        return TRUE;
    }
}
示例#4
0
static void
next_enumerator (GProxyAddressEnumeratorPrivate *priv)
{
  if (priv->proxy_address)
    return;

  while (priv->addr_enum == NULL && *priv->next_proxy)
    {
      GSocketConnectable *connectable = NULL;
      GProxy *proxy;

      priv->proxy_uri = *priv->next_proxy++;
      g_free (priv->proxy_type);
      priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);

      if (priv->proxy_type == NULL)
	continue;

      /* Assumes hostnames are supported for unknown protocols */
      priv->supports_hostname = TRUE;
      proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
      if (proxy)
        {
	  priv->supports_hostname = g_proxy_supports_hostname (proxy);
	  g_object_unref (proxy);
        }

      if (strcmp ("direct", priv->proxy_type) == 0)
	{
	  if (priv->connectable)
	    connectable = g_object_ref (priv->connectable);
	  else
	    connectable = g_network_address_new (priv->dest_hostname,
						 priv->dest_port);
	}
      else
	{
	  GError *error = NULL;

	  connectable = g_network_address_parse_uri (priv->proxy_uri, 0, &error);

	  if (error)
	    {
	      g_warning ("Invalid proxy URI '%s': %s",
			 priv->proxy_uri, error->message);
	      g_error_free (error);
	    }

	  save_userinfo (priv, priv->proxy_uri);
	}

      if (connectable)
	{
	  priv->addr_enum = g_socket_connectable_enumerate (connectable);
	  g_object_unref (connectable);
	}
    }
}
示例#5
0
static void
do_connectable (const char *arg, gboolean synchronous)
{
  char **parts;
  GSocketConnectable *connectable;
  GSocketAddressEnumerator *enumerator;

  if (strchr (arg, '/'))
    {
      /* service/protocol/domain */
      parts = g_strsplit (arg, "/", 3);
      if (!parts || !parts[2])
	usage ();

      connectable = g_network_service_new (parts[0], parts[1], parts[2]);
    }
  else
    {
      guint16 port;

      parts = g_strsplit (arg, ":", 2);
      if (parts && parts[1])
	{
	  arg = parts[0];
	  port = strtoul (parts[1], NULL, 10);
	}
      else
	port = 0;

      if (g_hostname_is_ip_address (arg))
	{
	  GInetAddress *addr = g_inet_address_new_from_string (arg);
	  GSocketAddress *sockaddr = g_inet_socket_address_new (addr, port);

	  g_object_unref (addr);
	  connectable = G_SOCKET_CONNECTABLE (sockaddr);
	}
      else
        connectable = g_network_address_new (arg, port);
    }

  enumerator = g_socket_connectable_enumerate (connectable);
  g_object_unref (connectable);

  if (synchronous)
    do_sync_connectable (enumerator);
  else
    do_async_connectable (enumerator);
}
示例#6
0
/* Tries to resolve priv->name as an IP address, possibly including an
 * IPv6 scope id.
 */
static void
maybe_resolve_ip (SoupAddress *addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	const char *pct, *ip;
	char *tmp = NULL;
	GSocketConnectable *gaddr;
	GSocketAddressEnumerator *sa_enum;
	GSocketAddress *saddr;

	if (priv->sockaddr || !priv->name)
		return;

	pct = strchr (priv->name, '%');
	if (pct)
		ip = tmp = g_strndup (priv->name, pct - priv->name);
	else
		ip = priv->name;

	if (!g_hostname_is_ip_address (ip)) {
		g_free (tmp);
		return;
	}
	g_free (tmp);

	gaddr = g_network_address_new (priv->name, priv->port);
	if (!gaddr)
		return;

	sa_enum = g_socket_connectable_enumerate (gaddr);
	saddr = g_socket_address_enumerator_next (sa_enum, NULL, NULL);
	if (saddr) {
		priv->n_addrs = 1;
		priv->sockaddr = g_new (struct sockaddr_storage, 1);
		if (!g_socket_address_to_native (saddr, priv->sockaddr,
						 sizeof (struct sockaddr_storage),
						 NULL)) {
			/* can't happen: We know the address format is supported
			 * and the buffer is large enough
			 */
			g_warn_if_reached ();
		}
		g_object_unref (saddr);
	}

	g_object_unref (sa_enum);
	g_object_unref (gaddr);
}
示例#7
0
/**
 * cockpit_stream_connect:
 * @name: name for pipe, for debugging
 * @address: socket address to connect to
 *
 * Create a new pipe connected as a client to the given socket
 * address, which can be a unix or inet address. Will connect
 * in stream mode.
 *
 * If the connection fails, a pipe is still returned. It will
 * close once the main loop is run with an appropriate problem.
 *
 * Returns: (transfer full): newly allocated CockpitStream.
 */
CockpitStream *
cockpit_stream_connect (const gchar *name,
                        GSocketConnectable *connectable,
                        CockpitStreamOptions *options)
{
  CockpitStream *stream;

  g_return_val_if_fail (G_IS_SOCKET_CONNECTABLE (connectable), NULL);

  stream = g_object_new (COCKPIT_TYPE_STREAM,
                         "io-stream", NULL,
                         "name", name,
                         NULL);

  if (options)
    stream->priv->options = cockpit_stream_options_ref (options);

  stream->priv->connecting = g_socket_connectable_enumerate (connectable);
  g_socket_address_enumerator_next_async (stream->priv->connecting, NULL,
                                          on_address_next, g_object_ref (stream));

  return stream;
}
示例#8
0
GSocketAddress *
cockpit_channel_parse_address (CockpitChannel *self,
                               gchar **possible_name)
{
  GSocketConnectable *connectable;
  GSocketAddressEnumerator *enumerator;
  GSocketAddress *address;
  GError *error = NULL;
  gchar *name = NULL;

  connectable = cockpit_channel_parse_connectable (self, &name);
  if (!connectable)
    return NULL;

  /* This is sync, but realistically, it doesn't matter for current use cases */
  enumerator = g_socket_connectable_enumerate (connectable);
  g_object_unref (connectable);

  address = g_socket_address_enumerator_next (enumerator, NULL, &error);
  g_object_unref (enumerator);

  if (error != NULL)
    {
      g_warning ("couldn't find address: %s: %s", name, error->message);
      cockpit_channel_close (self, "not-found");
      g_error_free (error);
      g_free (name);
      return NULL;
    }

  if (possible_name)
    *possible_name = name;
  else
    g_free (name);

  return address;
}
示例#9
0
文件: http.c 项目: ariosx/moloch
int moloch_http_connect(MolochConn_t *conn, char *name, int defaultport, int blocking)
{
    GError                   *error = 0;
    GSocketConnectable       *connectable;
    GSocketAddressEnumerator *enumerator;
    GSocketAddress           *sockaddr;

    if (config.logESRequests)
        LOG("Connecting %p %s", (void*)conn, name);


    connectable = g_network_address_parse(name, defaultport, &error);

    if (error) {
        LOG("%p: Couldn't parse connect string of %s", (void*)conn, name);
        exit(0);
    }

    conn->name = name;

    enumerator = g_socket_connectable_enumerate (connectable);
    g_object_unref(connectable);

    while (!conn->conn && (sockaddr = g_socket_address_enumerator_next (enumerator, NULL, &error)))
    {
        conn->conn = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &error);

        if (!error) {
            GValue value = G_VALUE_INIT;
            g_value_init (&value, G_TYPE_BOOLEAN);
            g_value_set_boolean (&value, blocking);
            g_object_set_property(G_OBJECT(conn->conn), "blocking", &value);

            g_socket_connect(conn->conn, sockaddr, NULL, &error);
        }

        if (error && error->code != G_IO_ERROR_PENDING) {
            g_object_unref (conn->conn);
            conn->conn = NULL;
        }
        g_object_unref (sockaddr);
    }
    g_object_unref (enumerator);

    if (conn->conn) {
        if (error) {
            g_error_free(error);
            error = 0;
        }
    } else if (error) {
        LOG("%p: Error: %s", (void*)conn, error->message);
    }

    if (error || !conn->conn) {
        conn->server->lastFailedConnect = time(0);
        return 1;
    }

    //g_object_ref (conn->conn);
    g_socket_set_keepalive(conn->conn, TRUE);
    int fd = g_socket_get_fd(conn->conn);
    moloch_watch_fd(fd, MOLOCH_GIO_READ_COND, moloch_http_read_cb, conn);

    int sendbuff = 0;
    socklen_t optlen = sizeof(sendbuff);

    int res = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
    if(res != -1 && sendbuff < 300000) {
        sendbuff = 300000;
        setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
    }

#ifdef TCP_KEEPIDLE
    res = getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &sendbuff, &optlen);
    if(res != -1 && sendbuff > 60*8) {
        sendbuff = 60*8;
        setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &sendbuff, sizeof(sendbuff));
    }
#endif

    return 0;
}
示例#10
0
int
main (int argc,
      char *argv[])
{
  GSocket *socket;
  GSocketAddress *src_address;
  GSocketAddress *address;
  GSocketType socket_type;
  GSocketFamily socket_family;
  GError *error = NULL;
  GOptionContext *context;
  GCancellable *cancellable;
  GSocketAddressEnumerator *enumerator;
  GSocketConnectable *connectable;

  g_thread_init (NULL);

  g_type_init ();

  context = g_option_context_new (" <hostname>[:port] - Test GSocket client stuff");
  g_option_context_add_main_entries (context, cmd_entries, NULL);
  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      g_printerr ("%s: %s\n", argv[0], error->message);
      return 1;
    }

  if (argc != 2)
    {
      g_printerr ("%s: %s\n", argv[0], "Need to specify hostname / unix socket name");
      return 1;
    }

  if (cancel_timeout)
    {
      cancellable = g_cancellable_new ();
      g_thread_create (cancel_thread, cancellable, FALSE, NULL);
    }
  else
    {
      cancellable = NULL;
    }

  loop = g_main_loop_new (NULL, FALSE);

  if (use_udp)
    socket_type = G_SOCKET_TYPE_DATAGRAM;
  else
    socket_type = G_SOCKET_TYPE_STREAM;

  if (unix_socket)
    socket_family = G_SOCKET_FAMILY_UNIX;
  else
    socket_family = G_SOCKET_FAMILY_IPV4;

  socket = g_socket_new (socket_family, socket_type, 0, &error);
  if (socket == NULL)
    {
      g_printerr ("%s: %s\n", argv[0], error->message);
      return 1;
    }

  if (read_timeout)
    g_socket_set_timeout (socket, read_timeout);

  if (unix_socket)
    {
      GSocketAddress *addr;

      addr = socket_address_from_string (argv[1]);
      if (addr == NULL)
	{
	  g_printerr ("%s: Could not parse '%s' as unix socket name\n", argv[0], argv[1]);
	  return 1;
	}
      connectable = G_SOCKET_CONNECTABLE (addr);
    }
  else
    {
      connectable = g_network_address_parse (argv[1], 7777, &error);
      if (connectable == NULL)
	{
	  g_printerr ("%s: %s\n", argv[0], error->message);
	  return 1;
	}
    }

  enumerator = g_socket_connectable_enumerate (connectable);
  while (TRUE)
    {
      address = g_socket_address_enumerator_next (enumerator, cancellable, &error);
      if (address == NULL)
	{
	  if (error == NULL)
	    g_printerr ("%s: No more addresses to try\n", argv[0]);
	  else
	    g_printerr ("%s: %s\n", argv[0], error->message);
	  return 1;
	}

      if (g_socket_connect (socket, address, cancellable, &error))
	break;
      g_printerr ("%s: Connection to %s failed: %s, trying next\n", argv[0], socket_address_to_string (address), error->message);
      g_error_free (error);
      error = NULL;

      g_object_unref (address);
    }
  g_object_unref (enumerator);
  g_object_unref (connectable);

  g_print ("Connected to %s\n",
	   socket_address_to_string (address));

  /* TODO: Test non-blocking connect */
  if (non_blocking)
    g_socket_set_blocking (socket, FALSE);

  src_address = g_socket_get_local_address (socket, &error);
  if (!src_address)
    {
      g_printerr ("Error getting local address: %s\n",
		  error->message);
      return 1;
    }
  g_print ("local address: %s\n",
	   socket_address_to_string (src_address));
  g_object_unref (src_address);

  while (TRUE)
    {
      gchar buffer[4096];
      gssize size;
      gsize to_send;

      if (fgets (buffer, sizeof buffer, stdin) == NULL)
	break;

      to_send = strlen (buffer);
      while (to_send > 0)
	{
	  ensure_condition (socket, "send", cancellable, G_IO_OUT);
	  if (use_udp)
	    size = g_socket_send_to (socket, address,
				     buffer, to_send,
				     cancellable, &error);
	  else
	    size = g_socket_send (socket, buffer, to_send,
				  cancellable, &error);

	  if (size < 0)
	    {
	      if (g_error_matches (error,
				   G_IO_ERROR,
				   G_IO_ERROR_WOULD_BLOCK))
		{
		  g_print ("socket send would block, handling\n");
		  g_error_free (error);
		  error = NULL;
		  continue;
		}
	      else
		{
		  g_printerr ("Error sending to socket: %s\n",
			      error->message);
		  return 1;
		}
	    }

	  g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size);

	  if (size == 0)
	    {
	      g_printerr ("Unexpected short write\n");
	      return 1;
	    }

	  to_send -= size;
	}

      ensure_condition (socket, "receive", cancellable, G_IO_IN);
      if (use_udp)
	size = g_socket_receive_from (socket, &src_address,
				      buffer, sizeof buffer,
				      cancellable, &error);
      else
	size = g_socket_receive (socket, buffer, sizeof buffer,
				 cancellable, &error);

      if (size < 0)
	{
	  g_printerr ("Error receiving from socket: %s\n",
		      error->message);
	  return 1;
	}

      if (size == 0)
	break;

      g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size);
      if (use_udp)
	g_print (" from %s", socket_address_to_string (src_address));
      g_print ("\n");

      if (verbose)
	g_print ("-------------------------\n"
		 "%.*s"
		 "-------------------------\n",
		 (int)size, buffer);

    }

  g_print ("closing socket\n");

  if (!g_socket_close (socket, &error))
    {
      g_printerr ("Error closing master socket: %s\n",
		  error->message);
      return 1;
    }

  g_object_unref (G_OBJECT (socket));
  g_object_unref (G_OBJECT (address));

  return 0;
}
示例#11
0
文件: http.c 项目: Amelos/moloch
int moloch_http_connect(MolochConn_t *conn, char *name, int defaultport, int blocking)
{
    GError                   *error = 0;
    GSocketConnectable       *connectable;
    GSocketAddressEnumerator *enumerator;
    GSocketAddress           *sockaddr;
    struct timeval            startTime;
    struct timeval            stopTime;

    gettimeofday(&startTime, NULL);

    connectable = g_network_address_parse(name, defaultport, &error);

    if (error) {
        LOG("%p: Couldn't parse connect string of %s", (void*)conn, name);
        exit(0);
    }

    conn->name = name;

    enumerator = g_socket_connectable_enumerate (connectable);
    g_object_unref(connectable);

    while (!conn->conn && (sockaddr = g_socket_address_enumerator_next (enumerator, NULL, &error)))
    {
        conn->conn = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &error);

        if (!error) {
            GValue value = G_VALUE_INIT;
            g_value_init (&value, G_TYPE_BOOLEAN);
            g_value_set_boolean (&value, blocking);
            g_object_set_property(G_OBJECT(conn->conn), "blocking", &value);
            g_socket_connect(conn->conn, sockaddr, NULL, &error);
        }

        if (error && error->code != G_IO_ERROR_PENDING) {
            g_object_unref (conn->conn);
            conn->conn = NULL;
        } else {
            struct sockaddr_in localAddress, remoteAddress;
            socklen_t addressLength = sizeof(localAddress);
            getsockname(g_socket_get_fd(conn->conn), (struct sockaddr*)&localAddress, &addressLength);
            g_socket_address_to_native(sockaddr, &remoteAddress, addressLength, NULL);

            
            char sessionId[MOLOCH_SESSIONID_LEN];
            moloch_session_id(sessionId, localAddress.sin_addr.s_addr, localAddress.sin_port,
                              remoteAddress.sin_addr.s_addr, remoteAddress.sin_port);

            DEBUGCONN("AAA connected %s %p %s", conn->server->names[0], conn, 
                      moloch_friendly_session_id(17, localAddress.sin_addr.s_addr, htons(localAddress.sin_port),
                                                 remoteAddress.sin_addr.s_addr, htons(remoteAddress.sin_port)));

            HASH_ADD(h_, connections, sessionId, conn);
            memcpy(&conn->sessionIda, sessionId, 8);
            memcpy(&conn->sessionIdb, sessionId+8, 4);
            conn->server->numConns++;
        }
        g_object_unref (sockaddr);
    }
    g_object_unref (enumerator);

    if (conn->conn) {
        if (error) {
            g_error_free(error);
            error = 0;
        }
    } else if (error) {
        LOG("%p: Error: %s", (void*)conn, error->message);
    }

    if (error || !conn->conn) {
        if (config.logESRequests)
            LOG("Connecting %p %s %d %d FAIL", (void*)conn, name, defaultport, blocking);
        conn->server->lastFailedConnect = time(0);
        return 1;
    }

    //g_object_ref (conn->conn);
    g_socket_set_keepalive(conn->conn, TRUE);
    int fd = g_socket_get_fd(conn->conn);

    conn->readWatch = moloch_watch_fd(fd, MOLOCH_GIO_READ_COND, moloch_http_read_cb, conn);
    if (!blocking) {
        conn->writeWatch = moloch_watch_fd(fd, G_IO_OUT, moloch_http_conn_cb, conn);
        DEBUGCONN("AAA connwritewatch %s %p fd:%d ww:%d", conn->server->names[0], conn, fd, conn->writeWatch);
    }

    int sendbuff = 0;
    socklen_t optlen = sizeof(sendbuff);

    int res = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
    if(res != -1 && sendbuff < 300000) {
        sendbuff = 300000;
        setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
    }

#ifdef TCP_KEEPIDLE
    res = getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &sendbuff, &optlen);
    if(res != -1 && sendbuff > 60*8) {
        sendbuff = 60*8;
        setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &sendbuff, sizeof(sendbuff));
    }
#endif

    gettimeofday(&stopTime, NULL);
    if (config.logESRequests)
        LOG("Connecting %p %s %d %d %ldms", (void*)conn, name, defaultport, blocking, 
            (stopTime.tv_sec - startTime.tv_sec)*1000 + (stopTime.tv_usec - startTime.tv_usec)/1000);

    return 0;
}
示例#12
0
static gboolean
make_connection (const char       *argument,
		 GTlsCertificate  *certificate,
		 GCancellable     *cancellable,
		 GSocket         **socket,
		 GSocketAddress  **address,
		 GIOStream       **connection,
		 GInputStream    **istream,
		 GOutputStream   **ostream,
		 GError          **error)
{
  GSocketType socket_type;
  GSocketFamily socket_family;
  GSocketAddressEnumerator *enumerator;
  GSocketConnectable *connectable;
  GSocketAddress *src_address;
  GTlsInteraction *interaction;
  GError *err = NULL;

  if (use_udp)
    socket_type = G_SOCKET_TYPE_DATAGRAM;
  else
    socket_type = G_SOCKET_TYPE_STREAM;

  if (unix_socket)
    socket_family = G_SOCKET_FAMILY_UNIX;
  else
    socket_family = G_SOCKET_FAMILY_IPV4;

  *socket = g_socket_new (socket_family, socket_type, 0, error);
  if (*socket == NULL)
    return FALSE;

  if (read_timeout)
    g_socket_set_timeout (*socket, read_timeout);

  if (unix_socket)
    {
      GSocketAddress *addr;

      addr = socket_address_from_string (argument);
      if (addr == NULL)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Could not parse '%s' as unix socket name", argument);
          return FALSE;
        }
      connectable = G_SOCKET_CONNECTABLE (addr);
    }
  else
    {
      connectable = g_network_address_parse (argument, 7777, error);
      if (connectable == NULL)
        return FALSE;
    }

  enumerator = g_socket_connectable_enumerate (connectable);
  while (TRUE)
    {
      *address = g_socket_address_enumerator_next (enumerator, cancellable, error);
      if (*address == NULL)
        {
          if (error != NULL && *error == NULL)
            g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                                 "No more addresses to try");
          return FALSE;
        }

      if (g_socket_connect (*socket, *address, cancellable, &err))
        break;
      g_message ("Connection to %s failed: %s, trying next", socket_address_to_string (*address), err->message);
      g_clear_error (&err);

      g_object_unref (*address);
    }
  g_object_unref (enumerator);

  g_print ("Connected to %s\n",
           socket_address_to_string (*address));

  src_address = g_socket_get_local_address (*socket, error);
  if (!src_address)
    {
      g_prefix_error (error, "Error getting local address: ");
      return FALSE;
    }

  g_print ("local address: %s\n",
           socket_address_to_string (src_address));
  g_object_unref (src_address);

  if (use_udp)
    {
      *connection = NULL;
      *istream = NULL;
      *ostream = NULL;
    }
  else
    *connection = G_IO_STREAM (g_socket_connection_factory_create_connection (*socket));

  if (tls)
    {
      GIOStream *tls_conn;

      tls_conn = g_tls_client_connection_new (*connection, connectable, error);
      if (!tls_conn)
        {
          g_prefix_error (error, "Could not create TLS connection: ");
          return FALSE;
        }

      g_signal_connect (tls_conn, "accept-certificate",
                        G_CALLBACK (accept_certificate), NULL);

      interaction = g_tls_console_interaction_new ();
      g_tls_connection_set_interaction (G_TLS_CONNECTION (tls_conn), interaction);
      g_object_unref (interaction);

      if (certificate)
        g_tls_connection_set_certificate (G_TLS_CONNECTION (tls_conn), certificate);

      g_object_unref (*connection);
      *connection = G_IO_STREAM (tls_conn);

      if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
                                       cancellable, error))
        {
          g_prefix_error (error, "Error during TLS handshake: ");
          return FALSE;
        }
    }
  g_object_unref (connectable);

  if (*connection)
    {
      *istream = g_io_stream_get_input_stream (*connection);
      *ostream = g_io_stream_get_output_stream (*connection);
    }

  return TRUE;
}