コード例 #1
0
static VALUE
rg_s_parse(G_GNUC_UNUSED VALUE self, VALUE host_and_port, VALUE default_port)
{
        GError *error = NULL;
        GSocketConnectable *connectable;

        connectable = g_network_address_parse(RVAL2CSTR(host_and_port),
                                              RVAL2GUINT16(default_port),
                                              &error);
        if (connectable == NULL)
                rbgio_raise_error(error);

        return GOBJ2RVAL_UNREF(connectable);
}
コード例 #2
0
ファイル: hotssh-tab.c プロジェクト: GNOME/hotssh
static void
on_create_and_connect (GtkButton     *button,
                       HotSshTab  *self)
{
  HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
  GError *local_error = NULL;
  GError **error = &local_error;
  GtkTreeIter iter;
  gs_unref_object GNetworkAddress *address = NULL;
  const char *hostname;
  gs_free char *stripped_hostname = NULL;
  const char *username;
  gs_free char *stripped_username = NULL;

  hostname = gtk_entry_get_text (GTK_ENTRY (priv->host_entry));
  stripped_hostname = g_strstrip (g_strdup (hostname));
  username = gtk_entry_get_text (GTK_ENTRY (priv->username_entry));
  stripped_username = g_strstrip (g_strdup (username));

  g_clear_object (&priv->cancellable);
  priv->cancellable = g_cancellable_new ();

  g_clear_object (&priv->address);
  address = (GNetworkAddress*)g_network_address_parse (stripped_hostname, 22, error);
  if (!address)
    {
      page_transition_take_error (self, local_error);
      return;
    }

  g_clear_pointer (&priv->connection_id, g_free);
  hotssh_hostdb_add_entry (hotssh_hostdb_get_instance (),
                           stripped_username,
                           (GNetworkAddress*)address,
                           &priv->connection_id);
  hotssh_hostdb_lookup_by_id (hotssh_hostdb_get_instance (),
                              priv->connection_id, &iter);
  /*
  gtk_tree_selection_select_iter (gtk_tree_view_get_selection ((GtkTreeView*)priv->connections_treeview),
                                  &iter);
  */

  page_transition (self, HOTSSH_TAB_PAGE_LIST_CONNECTIONS);
}
コード例 #3
0
ファイル: proxy.c プロジェクト: 492852238/SourceLearning
static void
use_network_address (gboolean synchronous)
{
  GError *error = NULL;
  GSocketAddressEnumerator *enumerator;
  GSocketConnectable *connectable;

  connectable = g_network_address_parse (info, -1, &error);

  if (error)
    {
      print_and_free_error (error);
      return;
    }

  enumerator = g_socket_connectable_proxy_enumerate (connectable);
  g_object_unref (connectable);

  printf ("Proxies for hostname and port '%s' are:\n", info);
  run_with_enumerator (synchronous, enumerator);

  g_object_unref (enumerator);
}
コード例 #4
0
ファイル: cockpitchannel.c プロジェクト: maxamillion/cockpit
GSocketConnectable *
cockpit_channel_parse_connectable (CockpitChannel *self,
                                   gchar **possible_name)
{
  const gchar *problem = "protocol-error";
  GSocketConnectable *connectable = NULL;
  const gchar *unix_path;
  const gchar *internal;
  JsonObject *options;
  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 (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 (cockpit_bridge_local_address)
        {
          connectable = g_network_address_parse (cockpit_bridge_local_address, port, &error);
          host = cockpit_bridge_local_address;
        }
      else
        {
          connectable = cockpit_loopback_new (port);
          host = "localhost";
        }
      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));
    }
  else if (internal)
    {
      gboolean reg = FALSE;
      if (internal_addresses)
        {
          reg = g_hash_table_lookup_extended(internal_addresses,
                                             internal,
                                             NULL,
                                             (gpointer *)&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);
    }
  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;
    }
  return connectable;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: socket-client.c プロジェクト: Andais/glib
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;
}
コード例 #7
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;
}
コード例 #8
0
ファイル: socket-client.c プロジェクト: endlessm/glib
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;
}
コード例 #9
0
ファイル: cockpitchannel.c プロジェクト: arilivigni/cockpit
static GSocketConnectable *
parse_address (CockpitChannel *self,
               gchar **possible_name,
               gboolean *local_address)
{
  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;
  gchar *name = NULL;
  gboolean open = FALSE;

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

  if (port != G_MAXINT64 && unix_path)
    {
      cockpit_channel_fail (self, "protocol-error", "cannot specify both \"port\" and \"unix\" options");
      goto out;
    }
  else if (port != G_MAXINT64)
    {
      if (port <= 0 || port > 65535)
        {
          cockpit_channel_fail (self, "protocol-error", "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)
        {
          cockpit_channel_fail (self, "internal-error",
                                "couldn't parse local address: %s: %s", host, error->message);
          goto out;
        }
      else
        {
          name = g_strdup_printf ("%s:%d", host, (gint)port);
        }
    }
  else if (unix_path)
    {
      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)
            cockpit_channel_close (self, "not-found");
          else
            cockpit_channel_fail (self, "not-found", "couldn't find internal address: %s", internal);
          goto out;
        }

      name = g_strdup (internal);
      connectable = g_object_ref (connectable);
      local = FALSE;
    }
  else
    {
      cockpit_channel_fail (self, "protocol-error",
                            "no \"port\" or \"unix\" or other address option for channel");
      goto out;
    }

  open = TRUE;

out:
  g_clear_error (&error);
  if (open)
    {
      if (possible_name)
          *possible_name = g_strdup (name);
      if (local_address)
        *local_address = local;
    }
  else
    {
      if (connectable)
        g_object_unref (connectable);
      connectable = NULL;
    }

  g_free (name);
  return connectable;
}