1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
19  */
20 
21 #include "config.h"
22 
23 #include "gproxy.h"
24 
25 #include "giomodule.h"
26 #include "giomodule-priv.h"
27 #include "glibintl.h"
28 
29 /**
30  * SECTION:gproxy
31  * @short_description: Interface for proxy handling
32  * @include: gio/gio.h
33  *
34  * A #GProxy handles connecting to a remote host via a given type of
35  * proxy server. It is implemented by the 'gio-proxy' extension point.
36  * The extensions are named after their proxy protocol name. As an
37  * example, a SOCKS5 proxy implementation can be retrieved with the
38  * name 'socks5' using the function
39  * g_io_extension_point_get_extension_by_name().
40  *
41  * Since: 2.26
42  **/
43 
G_DEFINE_INTERFACE(GProxy,g_proxy,G_TYPE_OBJECT)44 G_DEFINE_INTERFACE (GProxy, g_proxy, G_TYPE_OBJECT)
45 
46 static void
47 g_proxy_default_init (GProxyInterface *iface)
48 {
49 }
50 
51 /**
52  * g_proxy_get_default_for_protocol:
53  * @protocol: the proxy protocol name (e.g. http, socks, etc)
54  *
55  * Find the `gio-proxy` extension point for a proxy implementation that supports
56  * the specified protocol.
57  *
58  * Returns: (nullable) (transfer full): return a #GProxy or NULL if protocol
59  *               is not supported.
60  *
61  * Since: 2.26
62  **/
63 GProxy *
g_proxy_get_default_for_protocol(const gchar * protocol)64 g_proxy_get_default_for_protocol (const gchar *protocol)
65 {
66   GIOExtensionPoint *ep;
67   GIOExtension *extension;
68 
69   /* Ensure proxy modules loaded */
70   _g_io_modules_ensure_loaded ();
71 
72   ep = g_io_extension_point_lookup (G_PROXY_EXTENSION_POINT_NAME);
73 
74   extension = g_io_extension_point_get_extension_by_name (ep, protocol);
75 
76   if (extension)
77       return g_object_new (g_io_extension_get_type (extension), NULL);
78 
79   return NULL;
80 }
81 
82 /**
83  * g_proxy_connect:
84  * @proxy: a #GProxy
85  * @connection: a #GIOStream
86  * @proxy_address: a #GProxyAddress
87  * @cancellable: (nullable): a #GCancellable
88  * @error: return #GError
89  *
90  * Given @connection to communicate with a proxy (eg, a
91  * #GSocketConnection that is connected to the proxy server), this
92  * does the necessary handshake to connect to @proxy_address, and if
93  * required, wraps the #GIOStream to handle proxy payload.
94  *
95  * Returns: (transfer full): a #GIOStream that will replace @connection. This might
96  *               be the same as @connection, in which case a reference
97  *               will be added.
98  *
99  * Since: 2.26
100  */
101 GIOStream *
g_proxy_connect(GProxy * proxy,GIOStream * connection,GProxyAddress * proxy_address,GCancellable * cancellable,GError ** error)102 g_proxy_connect (GProxy            *proxy,
103 		 GIOStream         *connection,
104 		 GProxyAddress     *proxy_address,
105 		 GCancellable      *cancellable,
106 		 GError           **error)
107 {
108   GProxyInterface *iface;
109 
110   g_return_val_if_fail (G_IS_PROXY (proxy), NULL);
111 
112   iface = G_PROXY_GET_IFACE (proxy);
113 
114   return (* iface->connect) (proxy,
115 			     connection,
116 			     proxy_address,
117 			     cancellable,
118 			     error);
119 }
120 
121 /**
122  * g_proxy_connect_async:
123  * @proxy: a #GProxy
124  * @connection: a #GIOStream
125  * @proxy_address: a #GProxyAddress
126  * @cancellable: (nullable): a #GCancellable
127  * @callback: (scope async): a #GAsyncReadyCallback
128  * @user_data: (closure): callback data
129  *
130  * Asynchronous version of g_proxy_connect().
131  *
132  * Since: 2.26
133  */
134 void
g_proxy_connect_async(GProxy * proxy,GIOStream * connection,GProxyAddress * proxy_address,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)135 g_proxy_connect_async (GProxy               *proxy,
136 		       GIOStream            *connection,
137 		       GProxyAddress        *proxy_address,
138 		       GCancellable         *cancellable,
139 		       GAsyncReadyCallback   callback,
140 		       gpointer              user_data)
141 {
142   GProxyInterface *iface;
143 
144   g_return_if_fail (G_IS_PROXY (proxy));
145 
146   iface = G_PROXY_GET_IFACE (proxy);
147 
148   (* iface->connect_async) (proxy,
149 			    connection,
150 			    proxy_address,
151 			    cancellable,
152 			    callback,
153 			    user_data);
154 }
155 
156 /**
157  * g_proxy_connect_finish:
158  * @proxy: a #GProxy
159  * @result: a #GAsyncResult
160  * @error: return #GError
161  *
162  * See g_proxy_connect().
163  *
164  * Returns: (transfer full): a #GIOStream.
165  *
166  * Since: 2.26
167  */
168 GIOStream *
g_proxy_connect_finish(GProxy * proxy,GAsyncResult * result,GError ** error)169 g_proxy_connect_finish (GProxy       *proxy,
170 			GAsyncResult *result,
171 			GError      **error)
172 {
173   GProxyInterface *iface;
174 
175   g_return_val_if_fail (G_IS_PROXY (proxy), NULL);
176 
177   iface = G_PROXY_GET_IFACE (proxy);
178 
179   return (* iface->connect_finish) (proxy, result, error);
180 }
181 
182 /**
183  * g_proxy_supports_hostname:
184  * @proxy: a #GProxy
185  *
186  * Some proxy protocols expect to be passed a hostname, which they
187  * will resolve to an IP address themselves. Others, like SOCKS4, do
188  * not allow this. This function will return %FALSE if @proxy is
189  * implementing such a protocol. When %FALSE is returned, the caller
190  * should resolve the destination hostname first, and then pass a
191  * #GProxyAddress containing the stringified IP address to
192  * g_proxy_connect() or g_proxy_connect_async().
193  *
194  * Returns: %TRUE if hostname resolution is supported.
195  *
196  * Since: 2.26
197  */
198 gboolean
g_proxy_supports_hostname(GProxy * proxy)199 g_proxy_supports_hostname (GProxy *proxy)
200 {
201   GProxyInterface *iface;
202 
203   g_return_val_if_fail (G_IS_PROXY (proxy), FALSE);
204 
205   iface = G_PROXY_GET_IFACE (proxy);
206 
207   return (* iface->supports_hostname) (proxy);
208 }
209