コード例 #1
0
ファイル: arvfakegvcamera.c プロジェクト: Will-W/aravis
gboolean
_g_inet_socket_address_is_equal (GInetSocketAddress *a, GInetSocketAddress *b)
{
	GInetAddress *a_addr;
	GInetAddress *b_addr;
	char *a_str;
	char *b_str;
	gboolean result;

	if (!G_IS_INET_SOCKET_ADDRESS (a) ||
	    !G_IS_INET_SOCKET_ADDRESS (b))
		return FALSE;

	if (g_inet_socket_address_get_port (a) != g_inet_socket_address_get_port (b))
		return FALSE;

	a_addr = g_inet_socket_address_get_address (a);
	b_addr = g_inet_socket_address_get_address (b);

	a_str = g_inet_address_to_string (a_addr);
	b_str = g_inet_address_to_string (b_addr);

	/* TODO: find a better way to do inet address comparison */
	result = g_strcmp0 (a_str, b_str) == 0;

	g_free (a_str);
	g_free (b_str);

	return result;
}
コード例 #2
0
ファイル: cockpithandlers.c プロジェクト: pdonlon/cockpit
static gchar *
get_remote_address (GIOStream *io)
{
  GSocketAddress *remote = NULL;
  GSocketConnection *connection = NULL;
  GIOStream *base;
  gchar *result = NULL;

  if (G_IS_TLS_CONNECTION (io))
    {
      g_object_get (io, "base-io-stream", &base, NULL);
      if (G_IS_SOCKET_CONNECTION (base))
        connection = g_object_ref (base);
      g_object_unref (base);
    }
  else if (G_IS_SOCKET_CONNECTION (io))
    {
      connection = g_object_ref (io);
    }

  if (connection)
    remote = g_socket_connection_get_remote_address (connection, NULL);
  if (remote && G_IS_INET_SOCKET_ADDRESS (remote))
    result = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (remote)));

  if (remote)
    g_object_unref (remote);
  if (connection)
    g_object_unref (connection);

  return result;
}
コード例 #3
0
ファイル: resolver.c プロジェクト: batman52/dingux-code
static void
print_connectable_sockaddr (GSocketAddress *sockaddr,
                            GError         *error)
{
  char *phys;

  if (error)
    {
      printf ("Error:   %s\n", error->message);
      g_error_free (error);
    }
  else if (!G_IS_INET_SOCKET_ADDRESS (sockaddr))
    {
      printf ("Error:   Unexpected sockaddr type '%s'\n", g_type_name_from_instance ((GTypeInstance *)sockaddr));
      g_object_unref (sockaddr);
    }
  else
    {
      GInetSocketAddress *isa = G_INET_SOCKET_ADDRESS (sockaddr);
      phys = g_inet_address_to_string (g_inet_socket_address_get_address (isa));
      printf ("Address: %s%s%s:%d\n",
              strchr (phys, ':') ? "[" : "", phys, strchr (phys, ':') ? "]" : "",
              g_inet_socket_address_get_port (isa));
      g_free (phys);
      g_object_unref (sockaddr);
    }
}
コード例 #4
0
static void
do_lookup_by_name (GTask         *task,
                   gpointer       source_object,
                   gpointer       task_data,
                   GCancellable  *cancellable)
{
  const char *hostname = task_data;
  struct addrinfo *res = NULL;
  GList *addresses;
  gint retval;

  retval = getaddrinfo (hostname, NULL, &addrinfo_hints, &res);

  if (retval == 0)
    {
      struct addrinfo *ai;
      GSocketAddress *sockaddr;
      GInetAddress *addr;

      addresses = NULL;
      for (ai = res; ai; ai = ai->ai_next)
        {
          sockaddr = g_socket_address_new_from_native (ai->ai_addr, ai->ai_addrlen);
          if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr))
            continue;

          addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr));
          addresses = g_list_prepend (addresses, addr);
          g_object_unref (sockaddr);
        }

      if (addresses != NULL)
        {
          addresses = g_list_reverse (addresses);
          g_task_return_pointer (task, addresses,
                                 (GDestroyNotify)g_resolver_free_addresses);
        }
      else
        {
          /* All addresses failed to be converted to GSocketAddresses. */
          g_task_return_new_error (task,
                                   G_RESOLVER_ERROR,
                                   G_RESOLVER_ERROR_NOT_FOUND,
                                   _("Error resolving '%s': %s"),
                                   hostname,
                                   _("No valid addresses were found"));
        }
    }
  else
    {
      g_task_return_new_error (task,
                               G_RESOLVER_ERROR,
                               g_resolver_error_from_addrinfo_error (retval),
                               _("Error resolving '%s': %s"),
                               hostname, gai_strerror (retval));
    }

  if (res)
    freeaddrinfo (res);
}
コード例 #5
0
ファイル: socket-common.c プロジェクト: Andais/glib
static char *
socket_address_to_string (GSocketAddress *address)
{
  char *res = NULL;

  if (G_IS_INET_SOCKET_ADDRESS (address))
    {
      GInetAddress *inet_address;
      char *str;
      int port;

      inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
      str = g_inet_address_to_string (inet_address);
      port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
      res = g_strdup_printf ("%s:%d", str, port);
      g_free (str);
    }
#ifdef G_OS_UNIX
  else if (G_IS_UNIX_SOCKET_ADDRESS (address))
    {
      GUnixSocketAddress *uaddr = G_UNIX_SOCKET_ADDRESS (address);

      res = g_strdup_printf ("%s:%s",
			     unix_socket_address_types[g_unix_socket_address_get_address_type (uaddr)],
			     g_unix_socket_address_get_path (uaddr));
    }
#endif

  return res;
}
コード例 #6
0
ファイル: proxy.c プロジェクト: 492852238/SourceLearning
static void
print_proxy_address (GSocketAddress *sockaddr)
{
  GProxyAddress *proxy = NULL;

  if (sockaddr == NULL)
    {
      printf ("\tdirect://\n");
      return;
    }

  if (G_IS_PROXY_ADDRESS (sockaddr))
    {
      proxy = G_PROXY_ADDRESS (sockaddr);
      printf ("\t%s://", g_proxy_address_get_protocol(proxy));
    }
  else
    {
      printf ("\tdirect://");
    }

  if (G_IS_INET_SOCKET_ADDRESS (sockaddr))
    {
      GInetAddress *inetaddr;
      guint port;
      gchar *addr;

      g_object_get (sockaddr,
		    "address", &inetaddr,
		    "port", &port,
		    NULL);

      addr = g_inet_address_to_string (inetaddr);

      printf ("%s:%u", addr, port);

      g_free (addr);
    }

  if (proxy)
    {
      if (g_proxy_address_get_username(proxy))
        printf (" (Username: %s  Password: %s)",
                g_proxy_address_get_username(proxy),
                g_proxy_address_get_password(proxy));
      printf (" (Hostname: %s, Port: %i)",
              g_proxy_address_get_destination_hostname (proxy),
              g_proxy_address_get_destination_port (proxy));
    }

  printf ("\n");
}
コード例 #7
0
static void
g_tls_client_connection_gnutls_constructed (GObject *object)
{
  GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (object);
  GSocketConnection *base_conn;
  GSocketAddress *remote_addr;
  GInetAddress *iaddr;
  guint port;

  /* Create a TLS session ID. We base it on the IP address since
   * different hosts serving the same hostname/service will probably
   * not share the same session cache. We base it on the
   * server-identity because at least some servers will fail (rather
   * than just failing to resume the session) if we don't.
   * (https://bugs.launchpad.net/bugs/823325)
   */
  g_object_get (G_OBJECT (gnutls), "base-io-stream", &base_conn, NULL);
  if (G_IS_SOCKET_CONNECTION (base_conn))
    {
      remote_addr = g_socket_connection_get_remote_address (base_conn, NULL);
      if (G_IS_INET_SOCKET_ADDRESS (remote_addr))
	{
	  GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr);
	  const gchar *server_hostname;
	  gchar *addrstr, *session_id;

	  iaddr = g_inet_socket_address_get_address (isaddr);
	  port = g_inet_socket_address_get_port (isaddr);

	  addrstr = g_inet_address_to_string (iaddr);
	  server_hostname = get_server_identity (gnutls);
	  session_id = g_strdup_printf ("%s/%s/%d", addrstr,
					server_hostname ? server_hostname : "",
					port);
	  gnutls->priv->session_id = g_bytes_new_take (session_id, strlen (session_id));
	  g_free (addrstr);
	}
      g_object_unref (remote_addr);
    }
  g_object_unref (base_conn);

  if (G_OBJECT_CLASS (g_tls_client_connection_gnutls_parent_class)->constructed)
    G_OBJECT_CLASS (g_tls_client_connection_gnutls_parent_class)->constructed (object);
}
コード例 #8
0
ファイル: gvfsftpconnection.c プロジェクト: gicmo/gvfs
/**
 * g_vfs_ftp_connection_listen_data_connection:
 * @conn: a connection
 * @error: %NULL or location to take potential errors
 *
 * Initiates a listening socket that the FTP server can connect to. To accept 
 * connections and initialize data transfers, use 
 * g_vfs_ftp_connection_accept_data_connection().
 * This function supports what is known as "active FTP", while
 * g_vfs_ftp_connection_open_data_connection() is to be used for "passive FTP".
 *
 * Returns: the actual address the socket is listening on or %NULL on error
 **/
GSocketAddress *
g_vfs_ftp_connection_listen_data_connection (GVfsFtpConnection *conn,
                                             GError **          error)
{
  GSocketAddress *local, *addr;

  g_return_val_if_fail (conn != NULL, NULL);
  g_return_val_if_fail (conn->data == NULL, NULL);

  g_vfs_ftp_connection_stop_listening (conn);

  local = g_socket_connection_get_local_address (conn->connection, error);
  if (local == NULL)
    return NULL;

  conn->listen_socket = g_socket_new (g_socket_address_get_family (local),
                                      G_SOCKET_TYPE_STREAM,
                                      G_SOCKET_PROTOCOL_TCP,
                                      error);
  if (conn->listen_socket == NULL)
    return NULL;

  g_assert (G_IS_INET_SOCKET_ADDRESS (local));
  addr = g_inet_socket_address_new (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (local)), 0);
  g_object_unref (local);

  if (!g_socket_bind (conn->listen_socket, addr, TRUE, error) ||
      !g_socket_listen (conn->listen_socket, error) ||
      !(local = g_socket_get_local_address (conn->listen_socket, error)))
    {
      g_object_unref (addr);
      g_vfs_ftp_connection_stop_listening (conn);
      return NULL;
    }

  g_object_unref (addr);
  return local;
}
コード例 #9
0
ファイル: hotssh-tab.c プロジェクト: GNOME/hotssh
static void
on_socket_client_event (GSocketClient      *client,
                        GSocketClientEvent  event,
                        GSocketConnectable *connectable,
                        GIOStream          *connection,
                        gpointer            user_data)
{
  HotSshTab *self = HOTSSH_TAB (user_data);
  HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
  switch (event)
    {
    case G_SOCKET_CLIENT_RESOLVING:
      set_status_printf (self, _("Resolving '%s'…"),
                         priv->hostname);
      break;
    case G_SOCKET_CLIENT_CONNECTING:
      {
        GSocketConnection *socketconn = G_SOCKET_CONNECTION (connection);
        gs_unref_object GSocketAddress *remote_address =
          g_socket_connection_get_remote_address (socketconn, NULL);

        g_debug ("socket connecting remote=%p", remote_address);
        if (remote_address && G_IS_INET_SOCKET_ADDRESS (remote_address))
          {
            GInetAddress *inetaddr =
              g_inet_socket_address_get_address ((GInetSocketAddress*)remote_address);
            gs_free char *inet_str = g_inet_address_to_string (inetaddr);
            set_status_printf (self, _("Connecting to '%s'…"),
                               inet_str);
          }
        break;
      }
    default:
      break;
    }
}
コード例 #10
0
ファイル: cockpitwebserver.c プロジェクト: briceburg/cockpit
static gboolean
on_socket_input (GSocket *socket,
                 GIOCondition condition,
                 gpointer user_data)
{
  CockpitRequest *request = user_data;
  guchar first_byte;
  GInputVector vector[1] = { { &first_byte, 1 } };
  gint flags = G_SOCKET_MSG_PEEK;
  gboolean redirect_tls;
  gboolean is_tls;
  GSocketAddress *addr;
  GInetAddress *inet;
  GError *error = NULL;
  GIOStream *tls_stream;
  gssize num_read;

  num_read = g_socket_receive_message (socket,
                                       NULL, /* out GSocketAddress */
                                       vector,
                                       1,
                                       NULL, /* out GSocketControlMessage */
                                       NULL, /* out num_messages */
                                       &flags,
                                       NULL, /* GCancellable* */
                                       &error);
  if (num_read < 0)
    {
      /* Just wait and try again */
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
        {
          g_error_free (error);
          return TRUE;
        }

      if (!should_suppress_request_error (error))
        g_warning ("couldn't read from socket: %s", error->message);

      cockpit_request_finish (request);
      g_error_free (error);
      return FALSE;
    }

  is_tls = TRUE;
  redirect_tls = FALSE;

  /*
   * TLS streams are guaranteed to start with octet 22.. this way we can distinguish them
   * from regular HTTP requests
   */
  if (first_byte != 22 && first_byte != 0x80)
    {
      is_tls = FALSE;
      redirect_tls = TRUE;
      addr = g_socket_connection_get_remote_address (G_SOCKET_CONNECTION (request->io), NULL);
      if (G_IS_INET_SOCKET_ADDRESS (addr))
        {
          inet = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
          redirect_tls = !g_inet_address_get_is_loopback (inet);
        }
      g_clear_object (&addr);
    }

  if (is_tls)
    {
      tls_stream = g_tls_server_connection_new (request->io,
                                                request->web_server->certificate,
                                                &error);
      if (tls_stream == NULL)
        {
          g_warning ("couldn't create new TLS stream: %s", error->message);
          cockpit_request_finish (request);
          g_error_free (error);
          return FALSE;
        }

      g_object_unref (request->io);
      request->io = G_IO_STREAM (tls_stream);
    }
  else if (redirect_tls)
    {
      request->delayed_reply = 301;
    }

  start_request_input (request);

  /* No longer run *this* source */
  return FALSE;
}
コード例 #11
0
static gboolean
run (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GOptionContext) context = NULL;
  const char *dirpath;
  OtTrivialHttpd appstruct = { 0, };
  OtTrivialHttpd *app = &appstruct;
  glnx_unref_object SoupServer *server = NULL;
  g_autoptr(GFileMonitor) dirmon = NULL;

  context = g_option_context_new ("[DIR] - Simple webserver");
  g_option_context_add_main_entries (context, options, NULL);

  app->root_dfd = -1;

  if (!g_option_context_parse (context, &argc, &argv, error))
    goto out;

  if (argc > 1)
    dirpath = argv[1];
  else
    dirpath = ".";

  if (!glnx_opendirat (AT_FDCWD, dirpath, TRUE, &app->root_dfd, error))
    goto out;

  if (!(opt_random_500s_percentage >= 0 && opt_random_500s_percentage <= 99))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Invalid --random-500s=%u", opt_random_500s_percentage);
      goto out;
    }

  if (opt_log)
    {
      GOutputStream *stream = NULL;

      if (g_strcmp0 (opt_log, "-") == 0)
        {
          if (opt_daemonize)
            {
              ot_util_usage_error (context, "Cannot use --log-file=- and --daemonize at the same time", error);
              goto out;
            }
          stream = G_OUTPUT_STREAM (g_unix_output_stream_new (STDOUT_FILENO, FALSE));
        }
      else
        {
          g_autoptr(GFile) log_file = NULL;
          GFileOutputStream* log_stream;

          log_file = g_file_new_for_path (opt_log);
          log_stream = g_file_create (log_file,
                                      G_FILE_CREATE_PRIVATE,
                                      cancellable,
                                      error);
          if (!log_stream)
            goto out;
          stream = G_OUTPUT_STREAM (log_stream);
        }

      app->log = stream;
    }

#if SOUP_CHECK_VERSION(2, 48, 0)
  server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL);
  if (!soup_server_listen_all (server, opt_port, 0, error))
    goto out;
#else
  server = soup_server_new (SOUP_SERVER_PORT, opt_port,
                            SOUP_SERVER_SERVER_HEADER, "ostree-httpd ",
                            NULL);
#endif

  soup_server_add_handler (server, NULL, httpd_callback, app, NULL);
  if (opt_port_file)
    {
      g_autofree char *portstr = NULL;
#if SOUP_CHECK_VERSION(2, 48, 0)
      GSList *listeners = soup_server_get_listeners (server);
      g_autoptr(GSocket) listener = NULL;
      g_autoptr(GSocketAddress) addr = NULL;
      
      g_assert (listeners);
      listener = g_object_ref (listeners->data);
      g_slist_free (listeners);
      listeners = NULL;
      addr = g_socket_get_local_address (listener, error);
      if (!addr)
        goto out;

      g_assert (G_IS_INET_SOCKET_ADDRESS (addr));
      
      portstr = g_strdup_printf ("%u\n", g_inet_socket_address_get_port ((GInetSocketAddress*)addr));
#else
      portstr = g_strdup_printf ("%u\n", soup_server_get_port (server));
#endif

      if (g_strcmp0 ("-", opt_port_file) == 0)
        {
          fputs (portstr, stdout); // not g_print - this must go to stdout, not a handler
          fflush (stdout);
        }
      else if (!g_file_set_contents (opt_port_file, portstr, strlen (portstr), error))
        goto out;
    }
#if !SOUP_CHECK_VERSION(2, 48, 0)
  soup_server_run_async (server);
#endif
  
  if (opt_daemonize)
    {
      pid_t pid = fork();
      if (pid == -1)
        {
          int errsv = errno;
          g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                               g_strerror (errsv));
          goto out;
        }
      else if (pid > 0)
        {
          ret = TRUE;
          goto out;
        }
      /* Child, continue */
      if (setsid () < 0)
        err (1, "setsid");
      /* Daemonising: close stdout/stderr so $() et al work on us */
      if (freopen("/dev/null", "r", stdin) == NULL)
        err (1, "freopen");
      if (freopen("/dev/null", "w", stdout) == NULL)
        err (1, "freopen");
      if (freopen("/dev/null", "w", stderr) == NULL)
        err (1, "freopen");
    }
  else
    {
      /* Since we're used for testing purposes, let's just do this by
       * default.  This ensures we exit when our parent does.
       */
      if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0)
        {
          if (errno != ENOSYS)
            {
              glnx_set_error_from_errno (error);
              goto out;
            }
        }
    }

  app->running = TRUE;
  if (opt_autoexit)
    {
      gboolean is_symlink = FALSE;
      g_autoptr(GFile) root = NULL;
      g_autoptr(GFileInfo) info = NULL;

      root = g_file_new_for_path (dirpath);
      info = g_file_query_info (root,
                                G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                cancellable, error);
      if (!info)
        goto out;

      is_symlink = g_file_info_get_is_symlink (info);

      if (is_symlink)
        dirmon = g_file_monitor_file (root, 0, cancellable, error);
      else
        dirmon = g_file_monitor_directory (root, 0, cancellable, error);

      if (!dirmon)
        goto out;
      g_signal_connect (dirmon, "changed", G_CALLBACK (on_dir_changed), app);
    }
  httpd_log (app, "serving at root %s\n", dirpath);
  while (app->running)
    g_main_context_iteration (NULL, TRUE);

  ret = TRUE;
 out:
  if (app->root_dfd != -1)
    (void) close (app->root_dfd);
  g_clear_object (&app->log);
  return ret;
}
コード例 #12
0
ファイル: gsocketlistener.c プロジェクト: QuentinFiard/glib
/**
 * g_socket_listener_add_any_inet_port:
 * @listener: a #GSocketListener
 * @source_object: (allow-none): Optional #GObject identifying this source
 * @error: a #GError location to store the error occurring, or %NULL to
 * ignore.
 *
 * Listens for TCP connections on any available port number for both
 * IPv6 and IPv4 (if each is available).
 *
 * This is useful if you need to have a socket for incoming connections
 * but don't care about the specific port number.
 *
 * @source_object will be passed out in the various calls
 * to accept to identify this particular source, which is
 * useful if you're listening on multiple addresses and do
 * different things depending on what address is connected to.
 *
 * Returns: the port number, or 0 in case of failure.
 *
 * Since: 2.24
 **/
guint16
g_socket_listener_add_any_inet_port (GSocketListener  *listener,
				     GObject          *source_object,
                                     GError          **error)
{
  GSList *sockets_to_close = NULL;
  guint16 candidate_port = 0;
  GSocket *socket6 = NULL;
  GSocket *socket4 = NULL;
  gint attempts = 37;

  /*
   * multi-step process:
   *  - first, create an IPv6 socket.
   *  - if that fails, create an IPv4 socket and bind it to port 0 and
   *    that's it.  no retries if that fails (why would it?).
   *  - if our IPv6 socket also speaks IPv4 then we are done.
   *  - if not, then we need to create a IPv4 socket with the same port
   *    number.  this might fail, of course.  so we try this a bunch of
   *    times -- leaving the old IPv6 sockets open so that we get a
   *    different port number to try each time.
   *  - if all that fails then just give up.
   */

  while (attempts--)
    {
      GInetAddress *inet_address;
      GSocketAddress *address;
      gboolean result;

      g_assert (socket6 == NULL);
      socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6,
                              G_SOCKET_TYPE_STREAM,
                              G_SOCKET_PROTOCOL_DEFAULT,
                              NULL);

      if (socket6 != NULL)
        {
          inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
          address = g_inet_socket_address_new (inet_address, 0);
          g_object_unref (inet_address);
          result = g_socket_bind (socket6, address, TRUE, error);
          g_object_unref (address);

          if (!result ||
              !(address = g_socket_get_local_address (socket6, error)))
            {
              g_object_unref (socket6);
              socket6 = NULL;
              break;
            }

          g_assert (G_IS_INET_SOCKET_ADDRESS (address));
          candidate_port =
            g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
          g_assert (candidate_port != 0);
          g_object_unref (address);

          if (g_socket_speaks_ipv4 (socket6))
            break;
        }

      g_assert (socket4 == NULL);
      socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4,
                              G_SOCKET_TYPE_STREAM,
                              G_SOCKET_PROTOCOL_DEFAULT,
                              socket6 ? NULL : error);

      if (socket4 == NULL)
        /* IPv4 not supported.
         * if IPv6 is supported then candidate_port will be non-zero
         *   (and the error parameter above will have been NULL)
         * if IPv6 is unsupported then candidate_port will be zero
         *   (and error will have been set by the above call)
         */
        break;

      inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
      address = g_inet_socket_address_new (inet_address, candidate_port);
      g_object_unref (inet_address);
      /* a note on the 'error' clause below:
       *
       * if candidate_port is 0 then we report the error right away
       * since it is strange that this binding would fail at all.
       * otherwise, we ignore the error message (ie: NULL).
       *
       * the exception to this rule is the last time through the loop
       * (ie: attempts == 0) in which case we want to set the error
       * because failure here means that the entire call will fail and
       * we need something to show to the user.
       *
       * an english summary of the situation:  "if we gave a candidate
       * port number AND we have more attempts to try, then ignore the
       * error for now".
       */
      result = g_socket_bind (socket4, address, TRUE,
                              (candidate_port && attempts) ? NULL : error);
      g_object_unref (address);

      if (candidate_port)
        {
          g_assert (socket6 != NULL);

          if (result)
            /* got our candidate port successfully */
            break;

          else
            /* we failed to bind to the specified port.  try again. */
            {
              g_object_unref (socket4);
              socket4 = NULL;

              /* keep this open so we get a different port number */
              sockets_to_close = g_slist_prepend (sockets_to_close,
                                                  socket6);
              candidate_port = 0;
              socket6 = NULL;
            }
        }
      else
        /* we didn't tell it a port.  this means two things.
         *  - if we failed, then something really bad happened.
         *  - if we succeeded, then we need to find out the port number.
         */
        {
          g_assert (socket6 == NULL);

          if (!result ||
              !(address = g_socket_get_local_address (socket4, error)))
            {
              g_object_unref (socket4);
              socket4 = NULL;
              break;
            }

            g_assert (G_IS_INET_SOCKET_ADDRESS (address));
            candidate_port =
              g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
            g_assert (candidate_port != 0);
            g_object_unref (address);
            break;
        }
    }

  /* should only be non-zero if we have a socket */
  g_assert ((candidate_port != 0) == (socket4 || socket6));

  while (sockets_to_close)
    {
      g_object_unref (sockets_to_close->data);
      sockets_to_close = g_slist_delete_link (sockets_to_close,
                                              sockets_to_close);
    }

  /* now we actually listen() the sockets and add them to the listener */
  if (socket6 != NULL)
    {
      g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);
      if (!g_socket_listen (socket6, error))
        {
          g_object_unref (socket6);
          if (socket4)
            g_object_unref (socket4);

          return 0;
        }

      if (source_object)
        g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
                                 g_object_ref (source_object),
                                 g_object_unref);

      g_ptr_array_add (listener->priv->sockets, socket6);
    }

   if (socket4 != NULL)
    {
      g_socket_set_listen_backlog (socket4, listener->priv->listen_backlog);
      if (!g_socket_listen (socket4, error))
        {
          g_object_unref (socket4);
          if (socket6)
            g_object_unref (socket6);

          return 0;
        }

      if (source_object)
        g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
                                 g_object_ref (source_object),
                                 g_object_unref);

      g_ptr_array_add (listener->priv->sockets, socket4);
    }

  if ((socket4 != NULL || socket6 != NULL) &&
      G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
    G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);

  return candidate_port;
}
コード例 #13
0
static void
return_result (GTask *task)
{
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
  GSocketAddress *result;

  if (strcmp ("direct", priv->proxy_type) == 0)
    {
      result = priv->proxy_address;
      priv->proxy_address = NULL;
    }
  else
    {
      gchar *dest_hostname, *dest_protocol;
      GInetSocketAddress *inetsaddr;
      GInetAddress *inetaddr;
      guint16 port;

      if (!priv->supports_hostname)
	{
	  GInetAddress *dest_ip;

	  if (!priv->next_dest_ip)
	    priv->next_dest_ip = priv->dest_ips;

	  dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
	  dest_hostname = g_inet_address_to_string (dest_ip);

	  priv->next_dest_ip = g_list_next (priv->next_dest_ip);
	}
      else
	{
	  dest_hostname = g_strdup (priv->dest_hostname);
	}
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);

      g_return_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));

      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
      port = g_inet_socket_address_get_port (inetsaddr);

      result = g_object_new (G_TYPE_PROXY_ADDRESS,
			     "address", inetaddr,
			     "port", port,
			     "protocol", priv->proxy_type,
			     "destination-protocol", dest_protocol,
			     "destination-hostname", dest_hostname,
			     "destination-port", priv->dest_port,
			     "username", priv->proxy_username,
			     "password", priv->proxy_password,
			     "uri", priv->proxy_uri,
			     NULL);
      g_free (dest_hostname);
      g_free (dest_protocol);

      if (priv->supports_hostname || priv->next_dest_ip == NULL)
	{
	  g_object_unref (priv->proxy_address);
	  priv->proxy_address = NULL;
	}
    }

  g_task_return_pointer (task, result, g_object_unref);
  g_object_unref (task);
}
コード例 #14
0
static GSocketAddress *
g_proxy_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
				 GCancellable              *cancellable,
				 GError                   **error)
{
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
  GSocketAddress *result = NULL;
  GError *first_error = NULL;

  if (priv->proxies == NULL)
    {
      GProxyResolver *resolver = g_proxy_resolver_get_default ();
      priv->proxies = g_proxy_resolver_lookup (resolver,
					       priv->dest_uri,
					       cancellable,
					       error);
      priv->next_proxy = priv->proxies;

      if (priv->proxies == NULL)
	return NULL;
    }

  while (result == NULL && (*priv->next_proxy || priv->addr_enum))
    {
      gchar *dest_hostname;
      gchar *dest_protocol;
      GInetSocketAddress *inetsaddr;
      GInetAddress *inetaddr;
      guint16 port;

      next_enumerator (priv);

      if (!priv->addr_enum)
	continue;

      if (priv->proxy_address == NULL)
	{
	  priv->proxy_address = g_socket_address_enumerator_next (
				    priv->addr_enum,
				    cancellable,
				    first_error ? NULL : &first_error);
	}

      if (priv->proxy_address == NULL)
	{
	  g_object_unref (priv->addr_enum);
	  priv->addr_enum = NULL;

	  if (priv->dest_ips)
	    {
	      g_resolver_free_addresses (priv->dest_ips);
	      priv->dest_ips = NULL;
	    }

	  continue;
	}

      if (strcmp ("direct", priv->proxy_type) == 0)
	{
	  result = priv->proxy_address;
	  priv->proxy_address = NULL;
	  continue;
	}

      if (!priv->supports_hostname)
	{
	  GInetAddress *dest_ip;

	  if (!priv->dest_ips)
	    {
	      GResolver *resolver;

	      resolver = g_resolver_get_default();
	      priv->dest_ips = g_resolver_lookup_by_name (resolver,
							  priv->dest_hostname,
							  cancellable,
							  first_error ? NULL : &first_error);
	      g_object_unref (resolver);

	      if (!priv->dest_ips)
		{
		  g_object_unref (priv->proxy_address);
		  priv->proxy_address = NULL;
		  continue;
		}
	    }

	  if (!priv->next_dest_ip)
	    priv->next_dest_ip = priv->dest_ips;
	
	  dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
	  dest_hostname = g_inet_address_to_string (dest_ip);

	  priv->next_dest_ip = g_list_next (priv->next_dest_ip);
	}
      else
	{
	  dest_hostname = g_strdup (priv->dest_hostname);
	}
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
		 		  
      g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address),
			    NULL);

      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
      port = g_inet_socket_address_get_port (inetsaddr);

      result = g_object_new (G_TYPE_PROXY_ADDRESS,
			     "address", inetaddr,
			     "port", port,
			     "protocol", priv->proxy_type,
			     "destination-protocol", dest_protocol,
			     "destination-hostname", dest_hostname,
			     "destination-port", priv->dest_port,
			     "username", priv->proxy_username,
			     "password", priv->proxy_password,
			     "uri", priv->proxy_uri,
			     NULL);
      g_free (dest_hostname);
      g_free (dest_protocol);

      if (priv->supports_hostname || priv->next_dest_ip == NULL)
	{
	  g_object_unref (priv->proxy_address);
	  priv->proxy_address = NULL;
	}
    }

  if (result == NULL && first_error)
    g_propagate_error (error, first_error);
  else if (first_error)
    g_error_free (first_error);

  return result;
}
コード例 #15
0
static gboolean
g_network_monitor_base_can_reach (GNetworkMonitor      *monitor,
                                  GSocketConnectable   *connectable,
                                  GCancellable         *cancellable,
                                  GError              **error)
{
  GNetworkMonitorBasePrivate *priv = G_NETWORK_MONITOR_BASE (monitor)->priv;
  GSocketAddressEnumerator *enumerator;
  GSocketAddress *addr;

  if (priv->have_ipv4_default_route &&
      priv->have_ipv6_default_route)
    return TRUE;

  if (priv->networks->len == 0)
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
                           _("Network unreachable"));
      return FALSE;
    }

  enumerator = g_socket_connectable_proxy_enumerate (connectable);
  addr = g_socket_address_enumerator_next (enumerator, cancellable, error);
  if (!addr)
    {
      /* Either the user cancelled, or DNS resolution failed */
      g_object_unref (enumerator);
      return FALSE;
    }

  while (addr)
    {
      if (G_IS_INET_SOCKET_ADDRESS (addr))
        {
          GInetAddress *iaddr;
          int i;

          iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
          for (i = 0; i < priv->networks->len; i++)
            {
              if (g_inet_address_mask_matches (priv->networks->pdata[i], iaddr))
                {
                  g_object_unref (addr);
                  g_object_unref (enumerator);
                  return TRUE;
                }
            }
        }

      g_object_unref (addr);
      addr = g_socket_address_enumerator_next (enumerator, cancellable, error);
    }
  g_object_unref (enumerator);

  if (error && !*error)
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
                           _("Host unreachable"));
    }
  return FALSE;
}