Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2010 Collabora, Ltd.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include "gproxyresolver.h"
26 : :
27 : : #include <glib.h>
28 : : #include "glibintl.h"
29 : :
30 : : #include "gasyncresult.h"
31 : : #include "gcancellable.h"
32 : : #include "gtask.h"
33 : : #include "giomodule.h"
34 : : #include "gioerror.h"
35 : : #include "giomodule-priv.h"
36 : : #include "gnetworkingprivate.h"
37 : :
38 : : /**
39 : : * GProxyResolver:
40 : : *
41 : : * `GProxyResolver` provides synchronous and asynchronous network proxy
42 : : * resolution. `GProxyResolver` is used within [class@Gio.SocketClient] through
43 : : * the method [method@Gio.SocketConnectable.proxy_enumerate].
44 : : *
45 : : * Implementations of `GProxyResolver` based on
46 : : * [libproxy](https://github.com/libproxy/libproxy) and GNOME settings can be
47 : : * found in [glib-networking](https://gitlab.gnome.org/GNOME/glib-networking).
48 : : * GIO comes with an implementation for use inside Flatpak portals.
49 : : *
50 : : * Since: 2.26
51 : : */
52 : :
53 : : /**
54 : : * GProxyResolverInterface:
55 : : * @g_iface: The parent interface.
56 : : * @is_supported: the virtual function pointer for g_proxy_resolver_is_supported()
57 : : * @lookup: the virtual function pointer for g_proxy_resolver_lookup()
58 : : * @lookup_async: the virtual function pointer for
59 : : * g_proxy_resolver_lookup_async()
60 : : * @lookup_finish: the virtual function pointer for
61 : : * g_proxy_resolver_lookup_finish()
62 : : *
63 : : * The virtual function table for #GProxyResolver.
64 : : */
65 : :
66 : 2287 : G_DEFINE_INTERFACE (GProxyResolver, g_proxy_resolver, G_TYPE_OBJECT)
67 : :
68 : : static void
69 : 9 : g_proxy_resolver_default_init (GProxyResolverInterface *iface)
70 : : {
71 : 9 : }
72 : :
73 : : static GProxyResolver *proxy_resolver_default_singleton = NULL; /* (owned) (atomic) */
74 : :
75 : : /**
76 : : * g_proxy_resolver_get_default:
77 : : *
78 : : * Gets the default #GProxyResolver for the system.
79 : : *
80 : : * Returns: (not nullable) (transfer none): the default #GProxyResolver, which
81 : : * will be a dummy object if no proxy resolver is available
82 : : *
83 : : * Since: 2.26
84 : : */
85 : : GProxyResolver *
86 : 465 : g_proxy_resolver_get_default (void)
87 : : {
88 : 465 : if (g_once_init_enter_pointer (&proxy_resolver_default_singleton))
89 : : {
90 : : GProxyResolver *singleton;
91 : :
92 : 7 : singleton = _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
93 : : "GIO_USE_PROXY_RESOLVER",
94 : : (GIOModuleVerifyFunc) g_proxy_resolver_is_supported);
95 : :
96 : 7 : g_once_init_leave_pointer (&proxy_resolver_default_singleton, singleton);
97 : : }
98 : :
99 : 465 : return proxy_resolver_default_singleton;
100 : : }
101 : :
102 : : /**
103 : : * g_proxy_resolver_is_supported:
104 : : * @resolver: a #GProxyResolver
105 : : *
106 : : * Checks if @resolver can be used on this system. (This is used
107 : : * internally; g_proxy_resolver_get_default() will only return a proxy
108 : : * resolver that returns %TRUE for this method.)
109 : : *
110 : : * Returns: %TRUE if @resolver is supported.
111 : : *
112 : : * Since: 2.26
113 : : */
114 : : gboolean
115 : 12 : g_proxy_resolver_is_supported (GProxyResolver *resolver)
116 : : {
117 : : GProxyResolverInterface *iface;
118 : :
119 : 12 : g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), FALSE);
120 : :
121 : 12 : iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
122 : :
123 : 12 : return (* iface->is_supported) (resolver);
124 : : }
125 : :
126 : : /**
127 : : * g_proxy_resolver_lookup:
128 : : * @resolver: a #GProxyResolver
129 : : * @uri: a URI representing the destination to connect to
130 : : * @cancellable: (nullable): a #GCancellable, or %NULL
131 : : * @error: return location for a #GError, or %NULL
132 : : *
133 : : * Looks into the system proxy configuration to determine what proxy,
134 : : * if any, to use to connect to @uri. The returned proxy URIs are of
135 : : * the form `<protocol>://[user[:password]@]host[:port]` or
136 : : * `direct://`, where `<protocol>` could be http, rtsp, socks
137 : : * or other proxying protocol.
138 : : *
139 : : * If you don't know what network protocol is being used on the
140 : : * socket, you should use `none` as the URI protocol.
141 : : * In this case, the resolver might still return a generic proxy type
142 : : * (such as SOCKS), but would not return protocol-specific proxy types
143 : : * (such as http).
144 : : *
145 : : * `direct://` is used when no proxy is needed.
146 : : * Direct connection should not be attempted unless it is part of the
147 : : * returned array of proxies.
148 : : *
149 : : * Returns: (transfer full) (array zero-terminated=1): A
150 : : * NULL-terminated array of proxy URIs. Must be freed
151 : : * with g_strfreev().
152 : : *
153 : : * Since: 2.26
154 : : */
155 : : gchar **
156 : 298 : g_proxy_resolver_lookup (GProxyResolver *resolver,
157 : : const gchar *uri,
158 : : GCancellable *cancellable,
159 : : GError **error)
160 : : {
161 : : GProxyResolverInterface *iface;
162 : : gchar **proxy_uris;
163 : :
164 : 298 : g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
165 : 298 : g_return_val_if_fail (uri != NULL, NULL);
166 : :
167 : 298 : if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
168 : : {
169 : 2 : g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
170 : : "Invalid URI ā%sā", uri);
171 : 2 : return NULL;
172 : : }
173 : :
174 : 296 : iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
175 : :
176 : 296 : proxy_uris = (* iface->lookup) (resolver, uri, cancellable, error);
177 : 296 : if (proxy_uris == NULL && error != NULL)
178 : 0 : g_assert (*error != NULL);
179 : 296 : return proxy_uris;
180 : : }
181 : :
182 : : /**
183 : : * g_proxy_resolver_lookup_async:
184 : : * @resolver: a #GProxyResolver
185 : : * @uri: a URI representing the destination to connect to
186 : : * @cancellable: (nullable): a #GCancellable, or %NULL
187 : : * @callback: (scope async): callback to call after resolution completes
188 : : * @user_data: data for @callback
189 : : *
190 : : * Asynchronous lookup of proxy. See g_proxy_resolver_lookup() for more
191 : : * details.
192 : : *
193 : : * Since: 2.26
194 : : */
195 : : void
196 : 235 : g_proxy_resolver_lookup_async (GProxyResolver *resolver,
197 : : const gchar *uri,
198 : : GCancellable *cancellable,
199 : : GAsyncReadyCallback callback,
200 : : gpointer user_data)
201 : : {
202 : : GProxyResolverInterface *iface;
203 : 235 : GError *error = NULL;
204 : :
205 : 237 : g_return_if_fail (G_IS_PROXY_RESOLVER (resolver));
206 : 235 : g_return_if_fail (uri != NULL);
207 : :
208 : 235 : if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
209 : : {
210 : 2 : g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
211 : : "Invalid URI ā%sā", uri);
212 : 2 : g_task_report_error (resolver, callback, user_data,
213 : : g_proxy_resolver_lookup_async,
214 : 2 : g_steal_pointer (&error));
215 : 2 : return;
216 : : }
217 : :
218 : 233 : iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
219 : :
220 : 233 : (* iface->lookup_async) (resolver, uri, cancellable, callback, user_data);
221 : : }
222 : :
223 : : /**
224 : : * g_proxy_resolver_lookup_finish:
225 : : * @resolver: a #GProxyResolver
226 : : * @result: the result passed to your #GAsyncReadyCallback
227 : : * @error: return location for a #GError, or %NULL
228 : : *
229 : : * Call this function to obtain the array of proxy URIs when
230 : : * g_proxy_resolver_lookup_async() is complete. See
231 : : * g_proxy_resolver_lookup() for more details.
232 : : *
233 : : * Returns: (transfer full) (array zero-terminated=1): A
234 : : * NULL-terminated array of proxy URIs. Must be freed
235 : : * with g_strfreev().
236 : : *
237 : : * Since: 2.26
238 : : */
239 : : gchar **
240 : 235 : g_proxy_resolver_lookup_finish (GProxyResolver *resolver,
241 : : GAsyncResult *result,
242 : : GError **error)
243 : : {
244 : : GProxyResolverInterface *iface;
245 : : gchar **proxy_uris;
246 : :
247 : 235 : g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
248 : :
249 : 235 : if (g_async_result_is_tagged (result, g_proxy_resolver_lookup_async))
250 : 2 : return g_task_propagate_pointer (G_TASK (result), error);
251 : :
252 : 233 : iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
253 : :
254 : 233 : proxy_uris = (* iface->lookup_finish) (resolver, result, error);
255 : 233 : if (proxy_uris == NULL && error != NULL)
256 : 1 : g_assert (*error != NULL);
257 : 233 : return proxy_uris;
258 : : }
|