コード例 #1
0
static gboolean
try_mount (GVfsBackend *backend,
           GVfsJobMount *job,
           GMountSpec *mount_spec,
           GMountSource *mount_source,
           gboolean is_automount)
{
  GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend);

  const char *host, *portstr, *user;
  guint16 port = 548;

  host = g_mount_spec_get (mount_spec, "host");
  if (host == NULL)
  {
    g_vfs_job_failed (G_VFS_JOB (job),
                      G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
                      _("No hostname specified"));
    return TRUE;
  }

  portstr = g_mount_spec_get (mount_spec, "port");
  if (portstr != NULL)
  {
    port = atoi (portstr);
  }

  afp_backend->addr = G_NETWORK_ADDRESS (g_network_address_new (host, port));

  user = g_mount_spec_get (mount_spec, "user");
  afp_backend->user = g_strdup (user);

  return FALSE;
}
コード例 #2
0
ファイル: remote.c プロジェクト: fifteenhex/emcuetiti
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;
}
コード例 #3
0
ファイル: s52ais.c プロジェクト: pcannon67/S52
static GSocketConnection *_s52_init_sock(char *hostname, int port)
{
    g_print("s52ais:_init_s52_sock(): starting ..\n");

    GSocketClient *client = g_socket_client_new();
    if (NULL == client) {
        g_print("s52ais:_s52_init_sock(): client NULL  ..\n");
        return NULL;
    }

    GSocketConnectable *connectable = g_network_address_new(hostname, port);
    if (NULL == connectable) {
        g_print("s52ais:_s52_init_sock(): connectable NULL  ..\n");
        return NULL;
    }

    GError            *error = NULL;
    GSocketConnection *conn  = g_socket_client_connect(client, connectable, NULL, &error);

    g_object_unref(client);
    g_object_unref(connectable);

    if (NULL != error) {
        g_print("s52ais:_s52_init_sock():ERROR: %s\n", error->message);
        return NULL;
    }

    g_print("s52ais:_s52_init_sock(): connected to hostname:%s, port:%i\n", hostname, port);

    return conn;
}
コード例 #4
0
ファイル: xdmcp-client.c プロジェクト: tfarirayi1/lightdm
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;
    }
}
コード例 #5
0
static VALUE
rg_initialize(VALUE self, VALUE hostname, VALUE port)
{
        G_INITIALIZE(self, g_network_address_new(RVAL2CSTR(hostname),
                                                 RVAL2GUINT16(port)));

        return Qnil;
}
コード例 #6
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);
	}
    }
}
コード例 #7
0
ファイル: hotssh-tab.c プロジェクト: GNOME/hotssh
static void
on_connection_row_activated (GtkTreeView       *tree_view,
                             GtkTreePath       *path,
                             GtkTreeViewColumn *column,
                             gpointer           user_data)
{
  HotSshTab *self = user_data;
  HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
  GtkTreeIter iter;
  guint port;
  gs_unref_object GSocketConnectable *address = NULL;
  gs_unref_object GtkTreeModel *model = NULL;

  model = hotssh_hostdb_get_model (hotssh_hostdb_get_instance ());

  g_assert (gtk_tree_model_get_iter (model, &iter, path));

  g_clear_pointer (&priv->connection_id, g_free);
  g_clear_pointer (&priv->hostname, g_free);
  g_clear_pointer (&priv->username, g_free);
  gtk_tree_model_get (model, &iter,
                      HOTSSH_HOSTDB_COLUMN_ID,
                      &priv->connection_id,
                      HOTSSH_HOSTDB_COLUMN_HOSTNAME,
                      &priv->hostname,
                      HOTSSH_HOSTDB_COLUMN_PORT,
                      &port,
                      HOTSSH_HOSTDB_COLUMN_USERNAME,
                      &priv->username,
                      -1);

  g_clear_object (&priv->address);
  priv->address = g_network_address_new (priv->hostname, port);

  g_object_notify ((GObject*)self, "hostname");

  page_transition (self, HOTSSH_TAB_PAGE_CONNECTING);
  g_clear_object (&priv->connection);
  priv->connection = gssh_connection_new (priv->address, priv->username); 
  g_signal_connect (gssh_connection_get_socket_client (priv->connection),
                    "event", G_CALLBACK (on_socket_client_event), self);
  gssh_connection_set_interaction (priv->connection, (GTlsInteraction*)priv->password_interaction);
  g_signal_connect_object (priv->connection, "notify::state",
			   G_CALLBACK (on_connection_state_notify),
			   self, 0);
  g_debug ("connected, beginning handshake");
  gssh_connection_handshake_async (priv->connection, priv->cancellable,
				   on_connection_handshake, self);
  
  hotssh_hostdb_update_last_used (hotssh_hostdb_get_instance (),
                                  priv->connection_id);
}
コード例 #8
0
ファイル: resolver.c プロジェクト: batman52/dingux-code
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);
}
コード例 #9
0
ファイル: soup-address.c プロジェクト: I486DX2/libsoup
/* 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);
}
コード例 #10
0
EventdRelayServer *
eventd_relay_server_new(EventdCoreContext *core, const gchar *server_identity, gboolean accept_unknown_ca, gboolean use_websocket, gchar **forwards, gchar **subscriptions)
{
    EventdRelayServer *server;

    server = g_new0(EventdRelayServer, 1);
    server->core = core;

    if ( server_identity != NULL )
        server->server_identity = g_network_address_new(server_identity, 0);
    server->accept_unknown_ca = accept_unknown_ca;
    server->use_websocket = use_websocket;

    if ( forwards != NULL )
    {
        server->forward_all = ( forwards[0] == NULL );
        if ( ! server->forward_all )
        {
            server->forwards = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
            gchar **forward;
            for ( forward = forwards ; *forward != NULL ; ++forward )
                g_hash_table_add(server->forwards, *forward);
        }
        g_free(forwards);
    }

    server->subscribe = ( subscriptions != NULL );
    if ( server->subscribe && ( subscriptions[0] != NULL ) )
        server->subscriptions = subscriptions;
    else
        g_strfreev(subscriptions);

    server->reconnect = evhelpers_reconnect_new(5, 10,_eventd_relay_reconnect_callback, server);

    return server;
}
コード例 #11
0
ファイル: gdbusaddress.c プロジェクト: 183amir/glib
/* TODO: Declare an extension point called GDBusTransport (or similar)
 * and move code below to extensions implementing said extension
 * point. That way we can implement a D-Bus transport over X11 without
 * making libgio link to libX11...
 */
static GIOStream *
g_dbus_address_connect (const gchar   *address_entry,
                        const gchar   *transport_name,
                        GHashTable    *key_value_pairs,
                        GCancellable  *cancellable,
                        GError       **error)
{
  GIOStream *ret;
  GSocketConnectable *connectable;
  const gchar *nonce_file;

  connectable = NULL;
  ret = NULL;
  nonce_file = NULL;

  if (FALSE)
    {
    }
#ifdef G_OS_UNIX
  else if (g_strcmp0 (transport_name, "unix") == 0)
    {
      const gchar *path;
      const gchar *abstract;
      path = g_hash_table_lookup (key_value_pairs, "path");
      abstract = g_hash_table_lookup (key_value_pairs, "abstract");
      if ((path == NULL && abstract == NULL) || (path != NULL && abstract != NULL))
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address '%s' - the unix transport requires exactly one of the "
                         "keys 'path' or 'abstract' to be set"),
                       address_entry);
        }
      else if (path != NULL)
        {
          connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new (path));
        }
      else if (abstract != NULL)
        {
          connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new_with_type (abstract,
                                                                                   -1,
                                                                                   G_UNIX_SOCKET_ADDRESS_ABSTRACT));
        }
      else
        {
          g_assert_not_reached ();
        }
    }
#endif
  else if (g_strcmp0 (transport_name, "tcp") == 0 || g_strcmp0 (transport_name, "nonce-tcp") == 0)
    {
      const gchar *s;
      const gchar *host;
      glong port;
      gchar *endp;
      gboolean is_nonce;

      is_nonce = (g_strcmp0 (transport_name, "nonce-tcp") == 0);

      host = g_hash_table_lookup (key_value_pairs, "host");
      if (host == NULL)
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address '%s' - the host attribute is missing or malformed"),
                       address_entry);
          goto out;
        }

      s = g_hash_table_lookup (key_value_pairs, "port");
      if (s == NULL)
        s = "0";
      port = strtol (s, &endp, 10);
      if ((*s == '\0' || *endp != '\0') || port < 0 || port >= 65536)
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address '%s' - the port attribute is missing or malformed"),
                       address_entry);
          goto out;
        }


      if (is_nonce)
        {
          nonce_file = g_hash_table_lookup (key_value_pairs, "noncefile");
          if (nonce_file == NULL)
            {
              g_set_error (error,
                           G_IO_ERROR,
                           G_IO_ERROR_INVALID_ARGUMENT,
                           _("Error in address '%s' - the noncefile attribute is missing or malformed"),
                           address_entry);
              goto out;
            }
        }

      /* TODO: deal with family key/value-pair */
      connectable = g_network_address_new (host, port);
    }
  else if (g_strcmp0 (address_entry, "autolaunch:") == 0)
    {
      gchar *autolaunch_address;
      autolaunch_address = get_session_address_platform_specific (error);
      if (autolaunch_address != NULL)
        {
          ret = g_dbus_address_try_connect_one (autolaunch_address, NULL, cancellable, error);
          g_free (autolaunch_address);
          goto out;
        }
      else
        {
          g_prefix_error (error, _("Error auto-launching: "));
        }
    }
  else
    {
      g_set_error (error,
                   G_IO_ERROR,
                   G_IO_ERROR_INVALID_ARGUMENT,
                   _("Unknown or unsupported transport '%s' for address '%s'"),
                   transport_name,
                   address_entry);
    }

  if (connectable != NULL)
    {
      GSocketClient *client;
      GSocketConnection *connection;

      g_assert (ret == NULL);
      client = g_socket_client_new ();
      connection = g_socket_client_connect (client,
                                            connectable,
                                            cancellable,
                                            error);
      g_object_unref (connectable);
      g_object_unref (client);
      if (connection == NULL)
        goto out;

      ret = G_IO_STREAM (connection);

      if (nonce_file != NULL)
        {
          gchar nonce_contents[16 + 1];
          size_t num_bytes_read;
          FILE *f;

          /* be careful to read only 16 bytes - we also check that the file is only 16 bytes long */
          f = fopen (nonce_file, "rb");
          if (f == NULL)
            {
              g_set_error (error,
                           G_IO_ERROR,
                           G_IO_ERROR_INVALID_ARGUMENT,
                           _("Error opening nonce file '%s': %s"),
                           nonce_file,
                           g_strerror (errno));
              g_object_unref (ret);
              ret = NULL;
              goto out;
            }
          num_bytes_read = fread (nonce_contents,
                                  sizeof (gchar),
                                  16 + 1,
                                  f);
          if (num_bytes_read != 16)
            {
              if (num_bytes_read == 0)
                {
                  g_set_error (error,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_ARGUMENT,
                               _("Error reading from nonce file '%s': %s"),
                               nonce_file,
                               g_strerror (errno));
                }
              else
                {
                  g_set_error (error,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_ARGUMENT,
                               _("Error reading from nonce file '%s', expected 16 bytes, got %d"),
                               nonce_file,
                               (gint) num_bytes_read);
                }
              g_object_unref (ret);
              ret = NULL;
              fclose (f);
              goto out;
            }
          fclose (f);

          if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret),
                                          nonce_contents,
                                          16,
                                          NULL,
                                          cancellable,
                                          error))
            {
              g_prefix_error (error, _("Error writing contents of nonce file '%s' to stream:"), nonce_file);
              g_object_unref (ret);
              ret = NULL;
              goto out;
            }
        }
    }

 out:

  return ret;
}
コード例 #12
0
ファイル: cockpitchannel.c プロジェクト: abbra/cockpit
GSocketConnectable *
cockpit_channel_parse_connectable (CockpitChannel *self,
                                   gchar **possible_name,
                                   gboolean *local_address)
{
  const gchar *problem = "protocol-error";
  GSocketConnectable *connectable = NULL;
  const gchar *unix_path;
  const gchar *internal;
  const gchar *address;
  JsonObject *options;
  gboolean local = FALSE;
  GError *error = NULL;
  const gchar *host;
  gint64 port;

  options = self->priv->open_options;
  if (!cockpit_json_get_string (options, "unix", NULL, &unix_path))
    {
      g_warning ("invalid \"unix\" option in channel");
      goto out;
    }
  if (!cockpit_json_get_int (options, "port", G_MAXINT64, &port))
    {
      g_warning ("invalid \"port\" option in channel");
      goto out;
    }
  if (!cockpit_json_get_string (options, "internal", NULL, &internal))
    {
      g_warning ("invalid \"internal\" option in channel");
      goto out;
    }
  if (!cockpit_json_get_string (options, "address", NULL, &address))
    {
      g_warning ("invalid \"address\" option in channel");
      goto out;
    }

  if (port != G_MAXINT64 && unix_path)
    {
      g_warning ("cannot specify both \"port\" and \"unix\" options");
      goto out;
    }
  else if (port != G_MAXINT64)
    {
      if (port <= 0 || port > 65535)
        {
          g_warning ("received invalid \"port\" option");
          goto out;
        }

      if (address)
        {
          connectable = g_network_address_new (address, port);
          host = address;

          /* This isn't perfect, but matches the use case. Specify address => non-local */
          local = FALSE;
        }
      else if (cockpit_bridge_local_address)
        {
          connectable = g_network_address_parse (cockpit_bridge_local_address, port, &error);
          host = cockpit_bridge_local_address;
          local = TRUE;
        }
      else
        {
          connectable = cockpit_loopback_new (port);
          host = "localhost";
          local = TRUE;
        }

      if (error != NULL)
        {
          g_warning ("couldn't parse local address: %s: %s", host, error->message);
          problem = "internal-error";
          goto out;
        }
      else
        {
          if (possible_name)
            *possible_name = g_strdup_printf ("%s:%d", host, (gint)port);
        }
    }
  else if (unix_path)
    {
      if (possible_name)
        *possible_name = g_strdup (unix_path);
      connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new (unix_path));
      local = FALSE;
    }
  else if (internal)
    {
      gboolean reg = lookup_internal (internal, &connectable);

      if (!connectable)
        {
          if (!reg)
            g_warning ("couldn't find internal address: %s", internal);

          problem = "not-found";
          goto out;
        }

      if (possible_name)
        *possible_name = g_strdup (internal);
      connectable = g_object_ref (connectable);
      local = FALSE;
    }
  else
    {
      g_warning ("no \"port\" or \"unix\" or other address option for channel");
      goto out;
    }

  problem = NULL;

out:
  g_clear_error (&error);
  if (problem)
    {
      cockpit_channel_close (self, problem);
      if (connectable)
        g_object_unref (connectable);
      connectable = NULL;
    }
  else
    {
      if (local_address)
        *local_address = local;
    }
  return connectable;
}
コード例 #13
0
ファイル: gdbusaddress.c プロジェクト: nikolatesla/BitchXMPP
/* TODO: Declare an extension point called GDBusTransport (or similar)
 * and move code below to extensions implementing said extension
 * point. That way we can implement a D-Bus transport over X11 without
 * making libgio link to libX11...
 */
static GIOStream *
g_dbus_address_connect (const gchar   *address_entry,
                        const gchar   *transport_name,
                        GHashTable    *key_value_pairs,
                        GCancellable  *cancellable,
                        GError       **error)
{
  GIOStream *ret;
  GSocketConnectable *connectable;
  const gchar *nonce_file;

  connectable = NULL;
  ret = NULL;
  nonce_file = NULL;

  if (FALSE)
    {
    }
#ifdef G_OS_UNIX
  else if (g_strcmp0 (transport_name, "unix") == 0)
    {
      const gchar *path;
      const gchar *abstract;
      path = g_hash_table_lookup (key_value_pairs, "path");
      abstract = g_hash_table_lookup (key_value_pairs, "abstract");
      if ((path == NULL && abstract == NULL) || (path != NULL && abstract != NULL))
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address `%s' - the unix transport requires exactly one of the "
                         "keys `path' or `abstract' to be set"),
                       address_entry);
        }
      else if (path != NULL)
        {
          connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new (path));
        }
      else if (abstract != NULL)
        {
          connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new_with_type (abstract,
                                                                                   -1,
                                                                                   G_UNIX_SOCKET_ADDRESS_ABSTRACT));
        }
      else
        {
          g_assert_not_reached ();
        }
    }
#endif
  else if (g_strcmp0 (transport_name, "tcp") == 0 || g_strcmp0 (transport_name, "nonce-tcp") == 0)
    {
      const gchar *s;
      const gchar *host;
      guint port;
      gchar *endp;
      gboolean is_nonce;

      is_nonce = (g_strcmp0 (transport_name, "nonce-tcp") == 0);

      host = g_hash_table_lookup (key_value_pairs, "host");
      if (host == NULL)
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address `%s' - the host attribute is missing or malformed"),
                       address_entry);
          goto out;
        }

      s = g_hash_table_lookup (key_value_pairs, "port");
      if (s == NULL)
        s = "0";
      port = strtol (s, &endp, 10);
      if ((*s == '\0' || *endp != '\0') || port < 0 || port >= 65536)
        {
          g_set_error (error,
                       G_IO_ERROR,
                       G_IO_ERROR_INVALID_ARGUMENT,
                       _("Error in address `%s' - the port attribute is missing or malformed"),
                       address_entry);
          goto out;
        }


      if (is_nonce)
        {
          nonce_file = g_hash_table_lookup (key_value_pairs, "noncefile");
          if (nonce_file == NULL)
            {
              g_set_error (error,
                           G_IO_ERROR,
                           G_IO_ERROR_INVALID_ARGUMENT,
                           _("Error in address `%s' - the noncefile attribute is missing or malformed"),
                           address_entry);
              goto out;
            }
        }

      /* TODO: deal with family */
      connectable = g_network_address_new (host, port);
    }
  else
    {
      g_set_error (error,
                   G_IO_ERROR,
                   G_IO_ERROR_INVALID_ARGUMENT,
                   _("Unknown or unsupported transport `%s' for address `%s'"),
                   transport_name,
                   address_entry);
    }

  if (connectable != NULL)
    {
      GSocketClient *client;
      GSocketConnection *connection;

      g_assert (ret == NULL);
      client = g_socket_client_new ();
      connection = g_socket_client_connect (client,
                                            connectable,
                                            cancellable,
                                            error);
      g_object_unref (connectable);
      g_object_unref (client);
      if (connection == NULL)
        goto out;

      ret = G_IO_STREAM (connection);

      if (nonce_file != NULL)
        {
          gchar *nonce_contents;
          gsize nonce_length;

          /* TODO: too dangerous to read the entire file? (think denial-of-service etc.) */
          if (!g_file_get_contents (nonce_file,
                                    &nonce_contents,
                                    &nonce_length,
                                    error))
            {
              g_prefix_error (error, _("Error reading nonce file `%s':"), nonce_file);
              g_object_unref (ret);
              ret = NULL;
              goto out;
            }

          if (nonce_length != 16)
            {
              g_set_error (error,
                           G_IO_ERROR,
                           G_IO_ERROR_INVALID_ARGUMENT,
                           _("The nonce-file `%s' was %" G_GSIZE_FORMAT " bytes. Expected 16 bytes."),
                           nonce_file,
                           nonce_length);
              g_free (nonce_contents);
              g_object_unref (ret);
              ret = NULL;
              goto out;
            }

          if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret),
                                          nonce_contents,
                                          nonce_length,
                                          NULL,
                                          cancellable,
                                          error))
            {
              g_prefix_error (error, _("Error write contents of nonce file `%s' to stream:"), nonce_file);
              g_object_unref (ret);
              ret = NULL;
              g_free (nonce_contents);
              goto out;
            }
          g_free (nonce_contents);
        }
    }

 out:

  return ret;
}