[glib-networking/mcatanzaro/proxies: 16/16] wip




commit 713ebbf867e275ac8565f725c58ed5699a0de1ad
Author: Michael Catanzaro <mcatanzaro redhat com>
Date:   Fri Jul 2 15:43:01 2021 -0500

    wip

 meson.build                               |  19 +--
 proxy/basic/basic-module.c                |  65 ++++++++
 proxy/basic/gbasicproxyresolver.c         | 262 ++++++++++++++++++++++++++++++
 proxy/basic/gbasicproxyresolver.h         |  35 ++++
 proxy/basic/meson.build                   |  38 +++++
 proxy/gnome/meson.build                   |   2 +-
 proxy/libproxy/meson.build                |   2 +-
 proxy/tests/{libproxy.c => environment.c} |   0
 proxy/tests/meson.build                   |  15 +-
 9 files changed, 421 insertions(+), 17 deletions(-)
---
diff --git a/meson.build b/meson.build
index bf5f845c..4bf5f121 100644
--- a/meson.build
+++ b/meson.build
@@ -169,20 +169,19 @@ if ['darwin', 'ios'].contains(host_system)
   module_suffix = 'so'
 endif
 
-if libproxy_dep.found() or gsettings_desktop_schemas_dep.found()
-  proxy_test_programs = []
+proxy_test_programs = []
 
-  if libproxy_dep.found()
-    subdir('proxy/libproxy')
-  endif
-
-  if gsettings_desktop_schemas_dep.found()
-    subdir('proxy/gnome')
-  endif
+if libproxy_dep.found()
+subdir('proxy/libproxy')
+endif
 
-  subdir('proxy/tests')
+if gsettings_desktop_schemas_dep.found()
+subdir('proxy/gnome')
 endif
 
+subdir('proxy/basic')
+subdir('proxy/tests')
+
 subdir('tls/base')
 
 if gnutls_dep.found()
diff --git a/proxy/basic/basic-module.c b/proxy/basic/basic-module.c
new file mode 100644
index 00000000..3983bcfa
--- /dev/null
+++ b/proxy/basic/basic-module.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "gbasicproxyresolver.h"
+
+
+void
+g_io_basicproxy_load (GIOModule *module)
+{
+  gchar *locale_dir;
+#ifdef G_OS_WIN32
+  gchar *base_dir;
+#endif
+
+  g_basic_proxy_resolver_register (module);
+
+#ifdef G_OS_WIN32
+  base_dir = g_win32_get_package_installation_directory_of_module (NULL);
+  locale_dir = g_build_filename (base_dir, "share", "locale", NULL);
+  g_free (base_dir);
+#else
+  locale_dir = g_strdup (LOCALE_DIR);
+#endif
+
+  bindtextdomain (GETTEXT_PACKAGE, locale_dir);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  g_free (locale_dir);
+}
+
+void
+g_io_basicproxy_unload (GIOModule *module)
+{
+}
+
+gchar **
+g_io_basicproxy_query (void)
+{
+  gchar *eps[] = {
+    G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+    NULL
+  };
+  return g_strdupv (eps);
+}
diff --git a/proxy/basic/gbasicproxyresolver.c b/proxy/basic/gbasicproxyresolver.c
new file mode 100644
index 00000000..1379cc78
--- /dev/null
+++ b/proxy/basic/gbasicproxyresolver.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gbasicproxyresolver.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+struct _GBasicProxyResolver {
+  GObject parent_instance;
+};
+
+static void g_basic_proxy_resolver_iface_init (GProxyResolverInterface *iface);
+
+#ifdef GBASICPROXY_MODULE
+static void
+g_basic_proxy_resolver_class_finalize (GBasicProxyResolverClass *klass)
+{
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GBasicProxyResolver,
+                                g_basic_proxy_resolver,
+                                G_TYPE_OBJECT, 0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER,
+                                                               g_basic_proxy_resolver_iface_init))
+#else
+G_DEFINE_TYPE_EXTENDED (GBasicProxyResolver,
+                        g_basic_proxy_resolver,
+                        G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
+                                               g_basic_proxy_resolver_iface_init))
+#endif
+
+static void
+g_basic_proxy_resolver_init (GBasicProxyResolver *resolver)
+{
+}
+
+static gboolean
+g_basic_proxy_resolver_is_supported (GProxyResolver *object)
+{
+  return g_getenv ("ftp_proxy") || g_getenv ("FTP_PROXY") ||
+         g_getenv ("https_proxy") || g_getenv ("HTTPS_PROXY") ||
+         g_getenv ("http_proxy") || g_getenv ("HTTP_PROXY") ||
+         g_getenv ("no_proxy") || g_getenv ("NO_PROXY");
+}
+
+static gchar **
+proxy_results (const gchar *uri)
+{
+  gchar **proxies = g_new0 (gchar *, 2);
+  proxies[0] = g_strdup (uri);
+  return proxies;
+}
+
+static gboolean
+is_uri_ignored (const gchar *uri,
+                const gchar *ignore_pattern)
+{
+  GUri *guri = NULL;
+  GUri *ignore_guri = NULL;
+  const char *host;
+  const char *ignore_host;
+  int port;
+  int ignore_port;
+  gboolean ignored = FALSE;
+  GError *error = NULL;
+
+  guri = g_uri_parse (uri, G_URI_FLAGS_NONE, &error);
+  if (!guri)
+    {
+      g_warning ("Failed to parse URI %s: %s", uri, error->message);
+      g_error_free (error);
+      goto out;
+    }
+  host = g_uri_get_host (guri);
+  if (!host)
+    goto out;
+  port = g_uri_get_port (guri);
+
+  ignore_guri = g_uri_parse (ignore_pattern, G_URI_FLAGS_NONE, &error);
+  if (!ignore_guri)
+    {
+      g_warning ("Failed to parse URI %s: %s", ignore_pattern, error->message);
+      g_error_free (error);
+      goto out;
+    }
+  ignore_host = g_uri_get_host (ignore_guri);
+  if (!ignore_host)
+    goto out;
+  ignore_port = g_uri_get_port (ignore_guri);
+
+  /* libproxy's no_proxy config is implement in its ignore_domain.cpp,
+   * ignore_hostname.cpp, and ignore_ip.cpp. It's smarter than ours. I've just
+   * copied the basic domain checks from libproxy's ignore_domain.cpp. (Note the
+   * glob check is *really* strict.)
+   */
+
+       /* Hostname match (domain.com or domain.com:80) */
+       if (strcmp (host, ignore_host) == 0)
+               return (ignore_port == 0 || port == ignore_port);
+
+       /* Endswith (.domain.com or .domain.com:80) */
+       if (ignore_host[0] == '.' && g_str_has_suffix (host, ignore_host))
+               return (ignore_port == 0 || port == ignore_port);
+
+       /* Glob (*.domain.com or *.domain.com:80). */
+       if (ignore_host[0] == '*' && g_str_has_suffix (host, ignore_host + 1))
+               return (ignore_port == 0 || port == ignore_port);
+
+out:
+  if (guri)
+    g_uri_unref (guri);
+  if (ignore_guri)
+    g_uri_unref (ignore_guri);
+  return ignored;
+}
+
+static gchar **
+g_basic_proxy_resolver_lookup (GProxyResolver  *resolver,
+                               const gchar     *uri,
+                               GCancellable    *cancellable,
+                               GError         **error)
+{
+  gchar *scheme = g_uri_parse_scheme (uri);
+  gchar **no_proxy = NULL;
+
+  if (g_getenv ("no_proxy"))
+    no_proxy = g_strsplit (g_getenv ("no_proxy"), ",", -1);
+  else if (g_getenv ("NO_PROXY"))
+    no_proxy = g_strsplit (g_getenv ("NO_PROXY"), ",", -1);
+
+  if (no_proxy)
+    {
+      int len = g_strv_length (no_proxy);
+      gboolean ignored = FALSE;
+
+      for (int i = 0; i < len; i++)
+        {
+          if (is_uri_ignored (uri, no_proxy[i]))
+            {
+              ignored = TRUE;
+              break;
+            }
+        }
+      g_strfreev (no_proxy);
+
+      if (ignored)
+        return proxy_results ("direct://");
+    }
+
+  /* The order of precedence of the environment variables is copied from
+   * libproxy's config_envvar.cpp. We match it carefully. Note that the
+   * HTTP proxy is used for all schemes, not just HTTP.
+   */
+  if (g_ascii_strcasecmp (scheme, "ftp") == 0)
+    {
+      if (g_getenv ("ftp_proxy"))
+        return proxy_results (g_getenv ("ftp_proxy"));
+      if (g_getenv ("FTP_proxy"))
+        return proxy_results (g_getenv ("FTP_PROXY"));
+    }
+
+  if (g_ascii_strcasecmp (scheme, "https") == 0)
+    {
+      if (g_getenv ("https_proxy"))
+        return proxy_results (g_getenv ("https_proxy"));
+      if (g_getenv ("HTTPS_proxy"))
+        return proxy_results (g_getenv ("HTTPS_PROXY"));
+    }
+
+  if (g_getenv ("http_proxy"))
+    return proxy_results (g_getenv ("http_proxy"));
+
+  if (g_getenv ("HTTP_PROXY"))
+    return proxy_results (g_getenv ("HTTP_PROXY"));
+
+  return g_new0 (gchar *, 1);
+}
+
+static void
+g_basic_proxy_resolver_lookup_async (GProxyResolver      *resolver,
+                                     const gchar         *uri,
+                                     GCancellable        *cancellable,
+                                     GAsyncReadyCallback  callback,
+                                     gpointer             user_data)
+{
+  GTask *task;
+  gchar **proxies;
+
+  proxies = g_basic_proxy_resolver_lookup (resolver, uri, cancellable, NULL);
+
+  task = g_task_new (resolver, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_basic_proxy_resolver_lookup_async);
+  g_task_set_name (task, "[glib-networking] g_basic_proxy_resolver_lookup_async");
+  g_task_set_task_data (task, g_strdup (uri), g_free);
+  g_task_set_return_on_cancel (task, TRUE);
+  g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
+  g_object_unref (task);
+}
+
+static gchar **
+g_basic_proxy_resolver_lookup_finish (GProxyResolver     *resolver,
+                                      GAsyncResult       *result,
+                                      GError            **error)
+{
+  g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
+  g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == g_basic_proxy_resolver_lookup_async, 
NULL);
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+g_basic_proxy_resolver_class_init (GBasicProxyResolverClass *resolver_class)
+{
+}
+
+static void
+g_basic_proxy_resolver_iface_init (GProxyResolverInterface *iface)
+{
+  iface->is_supported = g_basic_proxy_resolver_is_supported;
+  iface->lookup = g_basic_proxy_resolver_lookup;
+  iface->lookup_async = g_basic_proxy_resolver_lookup_async;
+  iface->lookup_finish = g_basic_proxy_resolver_lookup_finish;
+}
+
+#ifdef GBASICPROXY_MODULE
+void
+g_basic_proxy_resolver_register (GIOModule *module)
+{
+  g_basic_proxy_resolver_register_type (G_TYPE_MODULE (module));
+  if (!module)
+    g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
+  g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+                                  g_basic_proxy_resolver_get_type(),
+                                  "basic",
+                                  100);
+}
+#endif
diff --git a/proxy/basic/gbasicproxyresolver.h b/proxy/basic/gbasicproxyresolver.h
new file mode 100644
index 00000000..0b10ab3f
--- /dev/null
+++ b/proxy/basic/gbasicproxyresolver.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_BASIC_PROXY_RESOLVER         (g_basic_proxy_resolver_get_type ())
+
+G_DECLARE_FINAL_TYPE (GBasicProxyResolver, g_basic_proxy_resolver, G, BASIC_PROXY_RESOLVER, GObject)
+
+void  g_basic_proxy_resolver_register (GIOModule *module);
+
+G_END_DECLS
diff --git a/proxy/basic/meson.build b/proxy/basic/meson.build
new file mode 100644
index 00000000..1aeed406
--- /dev/null
+++ b/proxy/basic/meson.build
@@ -0,0 +1,38 @@
+service_conf = configuration_data()
+service_conf.set('libexecdir', libexecdir)
+
+sources = files(
+  'gbasicproxyresolver.c',
+  'basic-module.c'
+)
+
+deps = [
+  gio_dep,
+  glib_dep,
+  gmodule_dep,
+  gobject_dep
+]
+
+module = shared_module(
+  'giobasicproxy',
+  sources: sources,
+  include_directories: top_inc,
+  dependencies: deps,
+  c_args: '-DGBASICPROXY_MODULE',
+  link_args: module_ldflags,
+  link_depends: symbol_map,
+  name_suffix: module_suffix,
+  install: true,
+  install_dir: gio_module_dir
+)
+
+if get_option('static_modules')
+  static_library('giobasicproxy',
+    objects: module.extract_all_objects(),
+    install: true,
+    install_dir: gio_module_dir
+  )
+  pkg.generate(module)
+endif
+
+proxy_test_programs += [['environment', 'basic', deps]]
diff --git a/proxy/gnome/meson.build b/proxy/gnome/meson.build
index 278ca328..dd4bc5be 100644
--- a/proxy/gnome/meson.build
+++ b/proxy/gnome/meson.build
@@ -32,4 +32,4 @@ if get_option('static_modules')
   pkg.generate(module)
 endif
 
-proxy_test_programs += [['gnome', deps]]
+proxy_test_programs += [['gnome', 'gnome', deps]]
diff --git a/proxy/libproxy/meson.build b/proxy/libproxy/meson.build
index 038bfa1e..7a766b3d 100644
--- a/proxy/libproxy/meson.build
+++ b/proxy/libproxy/meson.build
@@ -70,4 +70,4 @@ executable(
   install_dir: libexecdir
 )
 
-proxy_test_programs += [['libproxy', deps]]
+proxy_test_programs += [['environment', 'libproxy', deps]]
diff --git a/proxy/tests/libproxy.c b/proxy/tests/environment.c
similarity index 100%
rename from proxy/tests/libproxy.c
rename to proxy/tests/environment.c
diff --git a/proxy/tests/meson.build b/proxy/tests/meson.build
index 4e0079f0..fd385876 100644
--- a/proxy/tests/meson.build
+++ b/proxy/tests/meson.build
@@ -8,20 +8,25 @@ foreach program: proxy_test_programs
   test_conf.set('installed_tests_dir', installed_tests_execdir)
   test_conf.set('program', program[0])
 
+  test_name = program[0]
+  if program[0] != program[1]
+    test_name = program[0] + '-' + program[1]
+  endif
+
   if enable_installed_tests
     configure_file(
       input: test_template,
-      output: program[0] + '.test',
+      output: test_name + '.test',
       install_dir: installed_tests_metadir,
       configuration: test_conf
     )
   endif
 
   exe = executable(
-    program[0],
+    test_name,
     program[0] + '.c',
     include_directories: top_inc,
-    dependencies: program[1],
+    dependencies: program[2],
     c_args: cflags,
     install: enable_installed_tests,
     install_dir: installed_tests_execdir
@@ -30,11 +35,11 @@ foreach program: proxy_test_programs
   envs = [
     'G_TEST_SRCDIR=' + meson.current_source_dir(),
     'G_TEST_BUILDDIR=' + meson.current_build_dir(),
-    'GIO_MODULE_DIR=' + join_paths(meson.build_root(), 'proxy', program[0])
+    'GIO_MODULE_DIR=' + join_paths(meson.build_root(), 'proxy', program[1])
   ]
 
   test(
-    program[0],
+    test_name,
     exe,
     env: envs
   )


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]