Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
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 : : * Authors: Christian Kellner <gicmo@gnome.org>
21 : : * Samuel Cormier-Iijima <sciyoshi@gmail.com>
22 : : */
23 : :
24 : : #include <config.h>
25 : : #include <glib.h>
26 : : #include <string.h>
27 : :
28 : : #include "gsocketaddress.h"
29 : : #include "ginetaddress.h"
30 : : #include "ginetsocketaddress.h"
31 : : #include "gnativesocketaddress.h"
32 : : #include "gnetworkingprivate.h"
33 : : #include "gproxyaddress.h"
34 : : #include "gproxyaddressenumerator.h"
35 : : #include "gsocketaddressenumerator.h"
36 : : #include "gsocketconnectable.h"
37 : : #include "glibintl.h"
38 : : #include "gioenumtypes.h"
39 : :
40 : : #include "gunixsocketaddress.h"
41 : :
42 : : #ifdef G_OS_WIN32
43 : : #include "giowin32-afunix.h"
44 : : #endif
45 : :
46 : :
47 : : /**
48 : : * GSocketAddress:
49 : : *
50 : : * `GSocketAddress` is the equivalent of
51 : : * [`struct sockaddr`](man:sockaddr(3type)) and its subtypes in the BSD sockets
52 : : * API. This is an abstract class; use [class@Gio.InetSocketAddress] for
53 : : * internet sockets, or [class@Gio.UnixSocketAddress] for UNIX domain sockets.
54 : : */
55 : :
56 : : enum
57 : : {
58 : : PROP_NONE,
59 : : PROP_FAMILY
60 : : };
61 : :
62 : : static void g_socket_address_connectable_iface_init (GSocketConnectableIface *iface);
63 : : static GSocketAddressEnumerator *g_socket_address_connectable_enumerate (GSocketConnectable *connectable);
64 : : static GSocketAddressEnumerator *g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable);
65 : :
66 : 290847 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GSocketAddress, g_socket_address, G_TYPE_OBJECT,
67 : : G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
68 : : g_socket_address_connectable_iface_init))
69 : :
70 : : /**
71 : : * g_socket_address_get_family:
72 : : * @address: a #GSocketAddress
73 : : *
74 : : * Gets the socket family type of @address.
75 : : *
76 : : * Returns: the socket family type of @address
77 : : *
78 : : * Since: 2.22
79 : : */
80 : : GSocketFamily
81 : 1698 : g_socket_address_get_family (GSocketAddress *address)
82 : : {
83 : 1698 : g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), 0);
84 : :
85 : 1698 : return G_SOCKET_ADDRESS_GET_CLASS (address)->get_family (address);
86 : : }
87 : :
88 : : static void
89 : 1 : g_socket_address_get_property (GObject *object, guint prop_id,
90 : : GValue *value, GParamSpec *pspec)
91 : : {
92 : 1 : GSocketAddress *address = G_SOCKET_ADDRESS (object);
93 : :
94 : 1 : switch (prop_id)
95 : : {
96 : 1 : case PROP_FAMILY:
97 : 1 : g_value_set_enum (value, g_socket_address_get_family (address));
98 : 1 : break;
99 : :
100 : 0 : default:
101 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
102 : : }
103 : 1 : }
104 : :
105 : : static void
106 : 137 : g_socket_address_class_init (GSocketAddressClass *klass)
107 : : {
108 : 137 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
109 : :
110 : 137 : gobject_class->get_property = g_socket_address_get_property;
111 : :
112 : : /**
113 : : * GSocketAddress:family:
114 : : *
115 : : * The family of the socket address.
116 : : *
117 : : * Since: 2.22
118 : : */
119 : 137 : g_object_class_install_property (gobject_class, PROP_FAMILY,
120 : : g_param_spec_enum ("family", NULL, NULL,
121 : : G_TYPE_SOCKET_FAMILY,
122 : : G_SOCKET_FAMILY_INVALID,
123 : : G_PARAM_READABLE |
124 : : G_PARAM_STATIC_STRINGS));
125 : 137 : }
126 : :
127 : : static void
128 : 137 : g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_iface)
129 : : {
130 : 137 : connectable_iface->enumerate = g_socket_address_connectable_enumerate;
131 : 137 : connectable_iface->proxy_enumerate = g_socket_address_connectable_proxy_enumerate;
132 : : /* to_string() is implemented by subclasses */
133 : 137 : }
134 : :
135 : : static void
136 : 2202 : g_socket_address_init (GSocketAddress *address)
137 : : {
138 : :
139 : 2202 : }
140 : :
141 : : /**
142 : : * g_socket_address_get_native_size:
143 : : * @address: a #GSocketAddress
144 : : *
145 : : * Gets the size of @address's native struct sockaddr.
146 : : * You can use this to allocate memory to pass to
147 : : * g_socket_address_to_native().
148 : : *
149 : : * Returns: the size of the native struct sockaddr that
150 : : * @address represents
151 : : *
152 : : * Since: 2.22
153 : : */
154 : : gssize
155 : 1783 : g_socket_address_get_native_size (GSocketAddress *address)
156 : : {
157 : 1783 : g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), -1);
158 : :
159 : 1783 : return G_SOCKET_ADDRESS_GET_CLASS (address)->get_native_size (address);
160 : : }
161 : :
162 : : /**
163 : : * g_socket_address_to_native:
164 : : * @address: a #GSocketAddress
165 : : * @dest: a pointer to a memory location that will contain the native
166 : : * struct sockaddr
167 : : * @destlen: the size of @dest. Must be at least as large as
168 : : * g_socket_address_get_native_size()
169 : : * @error: #GError for error reporting, or %NULL to ignore
170 : : *
171 : : * Converts a #GSocketAddress to a native struct sockaddr, which can
172 : : * be passed to low-level functions like connect() or bind().
173 : : *
174 : : * If not enough space is available, a %G_IO_ERROR_NO_SPACE error
175 : : * is returned. If the address type is not known on the system
176 : : * then a %G_IO_ERROR_NOT_SUPPORTED error is returned.
177 : : *
178 : : * Returns: %TRUE if @dest was filled in, %FALSE on error
179 : : *
180 : : * Since: 2.22
181 : : */
182 : : gboolean
183 : 1868 : g_socket_address_to_native (GSocketAddress *address,
184 : : gpointer dest,
185 : : gsize destlen,
186 : : GError **error)
187 : : {
188 : 1868 : g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
189 : :
190 : 1868 : return G_SOCKET_ADDRESS_GET_CLASS (address)->to_native (address, dest, destlen, error);
191 : : }
192 : :
193 : : /**
194 : : * g_socket_address_new_from_native:
195 : : * @native: (not nullable): a pointer to a struct sockaddr
196 : : * @len: the size of the memory location pointed to by @native
197 : : *
198 : : * Creates a #GSocketAddress subclass corresponding to the native
199 : : * struct sockaddr @native.
200 : : *
201 : : * Returns: a new #GSocketAddress if @native could successfully
202 : : * be converted, otherwise %NULL
203 : : *
204 : : * Since: 2.22
205 : : */
206 : : GSocketAddress *
207 : 114 : g_socket_address_new_from_native (gpointer native,
208 : : gsize len)
209 : : {
210 : : gshort family;
211 : :
212 : 114 : if (len < sizeof (gshort))
213 : 0 : return NULL;
214 : :
215 : 114 : family = ((struct sockaddr *) native)->sa_family;
216 : :
217 : 114 : if (family == AF_UNSPEC)
218 : 0 : return NULL;
219 : :
220 : 114 : if (family == AF_INET)
221 : : {
222 : 42 : struct sockaddr_in *addr = (struct sockaddr_in *) native;
223 : : GInetAddress *iaddr;
224 : : GSocketAddress *sockaddr;
225 : :
226 : 42 : if (len < sizeof (*addr))
227 : 0 : return NULL;
228 : :
229 : 42 : iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
230 : 42 : sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin_port));
231 : 42 : g_object_unref (iaddr);
232 : 42 : return sockaddr;
233 : : }
234 : :
235 : 72 : if (family == AF_INET6)
236 : : {
237 : 29 : struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
238 : : GInetAddress *iaddr;
239 : : GSocketAddress *sockaddr;
240 : :
241 : 29 : if (len < sizeof (*addr))
242 : 0 : return NULL;
243 : :
244 : 29 : if (IN6_IS_ADDR_V4MAPPED (&(addr->sin6_addr)))
245 : : {
246 : : struct sockaddr_in sin_addr;
247 : :
248 : 2 : sin_addr.sin_family = AF_INET;
249 : 2 : sin_addr.sin_port = addr->sin6_port;
250 : 2 : memcpy (&(sin_addr.sin_addr.s_addr), addr->sin6_addr.s6_addr + 12, 4);
251 : 2 : iaddr = g_inet_address_new_from_bytes ((guint8 *) &(sin_addr.sin_addr), AF_INET);
252 : : }
253 : : else
254 : : {
255 : 27 : iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
256 : : }
257 : :
258 : 29 : sockaddr = g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
259 : : "address", iaddr,
260 : 29 : "port", g_ntohs (addr->sin6_port),
261 : : "flowinfo", addr->sin6_flowinfo,
262 : : "scope_id", addr->sin6_scope_id,
263 : : NULL);
264 : 29 : g_object_unref (iaddr);
265 : 29 : return sockaddr;
266 : : }
267 : :
268 : 43 : if (family == AF_UNIX)
269 : : {
270 : 1 : struct sockaddr_un *addr = (struct sockaddr_un *) native;
271 : 1 : gint path_len = len - G_STRUCT_OFFSET (struct sockaddr_un, sun_path);
272 : :
273 : 1 : if (path_len == 0)
274 : : {
275 : 1 : return g_unix_socket_address_new_with_type ("", 0,
276 : : G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
277 : : }
278 : 0 : else if (addr->sun_path[0] == 0)
279 : : {
280 : 0 : if (!g_unix_socket_address_abstract_names_supported ())
281 : : {
282 : 0 : return g_unix_socket_address_new_with_type ("", 0,
283 : : G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
284 : : }
285 : 0 : else if (len < sizeof (*addr))
286 : : {
287 : 0 : return g_unix_socket_address_new_with_type (addr->sun_path + 1,
288 : : path_len - 1,
289 : : G_UNIX_SOCKET_ADDRESS_ABSTRACT);
290 : : }
291 : : else
292 : : {
293 : 0 : return g_unix_socket_address_new_with_type (addr->sun_path + 1,
294 : : path_len - 1,
295 : : G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
296 : : }
297 : : }
298 : : else
299 : 0 : return g_unix_socket_address_new (addr->sun_path);
300 : : }
301 : :
302 : 42 : return g_native_socket_address_new (native, len);
303 : : }
304 : :
305 : :
306 : : #define G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (_g_socket_address_address_enumerator_get_type ())
307 : : #define G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR, GSocketAddressAddressEnumerator))
308 : :
309 : : typedef struct {
310 : : GSocketAddressEnumerator parent_instance;
311 : :
312 : : GSocketAddress *sockaddr;
313 : : } GSocketAddressAddressEnumerator;
314 : :
315 : : typedef struct {
316 : : GSocketAddressEnumeratorClass parent_class;
317 : :
318 : : } GSocketAddressAddressEnumeratorClass;
319 : :
320 : : static GType _g_socket_address_address_enumerator_get_type (void);
321 : 6557 : G_DEFINE_TYPE (GSocketAddressAddressEnumerator, _g_socket_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
322 : :
323 : : static void
324 : 2047 : g_socket_address_address_enumerator_finalize (GObject *object)
325 : : {
326 : : GSocketAddressAddressEnumerator *sockaddr_enum =
327 : 2047 : G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (object);
328 : :
329 : 2047 : if (sockaddr_enum->sockaddr)
330 : 0 : g_object_unref (sockaddr_enum->sockaddr);
331 : :
332 : 2047 : G_OBJECT_CLASS (_g_socket_address_address_enumerator_parent_class)->finalize (object);
333 : 2047 : }
334 : :
335 : : static GSocketAddress *
336 : 2225 : g_socket_address_address_enumerator_next (GSocketAddressEnumerator *enumerator,
337 : : GCancellable *cancellable,
338 : : GError **error)
339 : : {
340 : : GSocketAddressAddressEnumerator *sockaddr_enum =
341 : 2225 : G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
342 : :
343 : 2225 : if (sockaddr_enum->sockaddr)
344 : : {
345 : 2047 : GSocketAddress *ret = sockaddr_enum->sockaddr;
346 : :
347 : 2047 : sockaddr_enum->sockaddr = NULL;
348 : 2047 : return ret;
349 : : }
350 : : else
351 : 178 : return NULL;
352 : : }
353 : :
354 : : static void
355 : 2047 : _g_socket_address_address_enumerator_init (GSocketAddressAddressEnumerator *enumerator)
356 : : {
357 : 2047 : }
358 : :
359 : : static void
360 : 119 : _g_socket_address_address_enumerator_class_init (GSocketAddressAddressEnumeratorClass *sockaddrenum_class)
361 : : {
362 : 119 : GObjectClass *object_class = G_OBJECT_CLASS (sockaddrenum_class);
363 : : GSocketAddressEnumeratorClass *enumerator_class =
364 : 119 : G_SOCKET_ADDRESS_ENUMERATOR_CLASS (sockaddrenum_class);
365 : :
366 : 119 : enumerator_class->next = g_socket_address_address_enumerator_next;
367 : 119 : object_class->finalize = g_socket_address_address_enumerator_finalize;
368 : 119 : }
369 : :
370 : : static GSocketAddressEnumerator *
371 : 2047 : g_socket_address_connectable_enumerate (GSocketConnectable *connectable)
372 : : {
373 : : GSocketAddressAddressEnumerator *sockaddr_enum;
374 : :
375 : 2047 : sockaddr_enum = g_object_new (G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR, NULL);
376 : 2047 : sockaddr_enum->sockaddr = g_object_ref (G_SOCKET_ADDRESS (connectable));
377 : :
378 : 2047 : return (GSocketAddressEnumerator *)sockaddr_enum;
379 : : }
380 : :
381 : : static GSocketAddressEnumerator *
382 : 430 : g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
383 : : {
384 : 430 : GSocketAddressEnumerator *addr_enum = NULL;
385 : :
386 : 430 : g_assert (connectable != NULL);
387 : :
388 : 430 : if (G_IS_INET_SOCKET_ADDRESS (connectable) &&
389 : 424 : !G_IS_PROXY_ADDRESS (connectable))
390 : 424 : {
391 : : GInetAddress *addr;
392 : : guint port;
393 : : gchar *uri;
394 : : gchar *ip;
395 : :
396 : 424 : g_object_get (connectable, "address", &addr, "port", &port, NULL);
397 : :
398 : 424 : ip = g_inet_address_to_string (addr);
399 : 424 : uri = g_uri_join (G_URI_FLAGS_NONE, "none", NULL, ip, port, "", NULL, NULL);
400 : :
401 : 424 : addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
402 : : "connectable", connectable,
403 : : "uri", uri,
404 : : NULL);
405 : :
406 : 424 : g_object_unref (addr);
407 : 424 : g_free (ip);
408 : 424 : g_free (uri);
409 : : }
410 : : else
411 : : {
412 : 6 : addr_enum = g_socket_address_connectable_enumerate (connectable);
413 : : }
414 : :
415 : 430 : return addr_enum;
416 : : }
|