/src/glib/gio/gsocketaddressenumerator.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* GIO - GLib Input, Output and Streaming Library |
2 | | * |
3 | | * Copyright (C) 2008 Red Hat, Inc. |
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 | | |
21 | | #include "config.h" |
22 | | #include "gsocketaddressenumerator.h" |
23 | | #include "glibintl.h" |
24 | | |
25 | | #include "gtask.h" |
26 | | |
27 | | /** |
28 | | * GSocketAddressEnumerator: |
29 | | * |
30 | | * `GSocketAddressEnumerator` is an enumerator type for |
31 | | * [class@Gio.SocketAddress] instances. It is returned by enumeration functions |
32 | | * such as [method@Gio.SocketConnectable.enumerate], which returns a |
33 | | * `GSocketAddressEnumerator` to list each [class@Gio.SocketAddress] which could |
34 | | * be used to connect to that [iface@Gio.SocketConnectable]. |
35 | | * |
36 | | * Enumeration is typically a blocking operation, so the asynchronous methods |
37 | | * [method@Gio.SocketAddressEnumerator.next_async] and |
38 | | * [method@Gio.SocketAddressEnumerator.next_finish] should be used where |
39 | | * possible. |
40 | | * |
41 | | * Each `GSocketAddressEnumerator` can only be enumerated once. Once |
42 | | * [method@Gio.SocketAddressEnumerator.next] has returned `NULL`, further |
43 | | * enumeration with that `GSocketAddressEnumerator` is not possible, and it can |
44 | | * be unreffed. |
45 | | */ |
46 | | |
47 | | G_DEFINE_ABSTRACT_TYPE (GSocketAddressEnumerator, g_socket_address_enumerator, G_TYPE_OBJECT) |
48 | | |
49 | | static void g_socket_address_enumerator_real_next_async (GSocketAddressEnumerator *enumerator, |
50 | | GCancellable *cancellable, |
51 | | GAsyncReadyCallback callback, |
52 | | gpointer user_data); |
53 | | static GSocketAddress *g_socket_address_enumerator_real_next_finish (GSocketAddressEnumerator *enumerator, |
54 | | GAsyncResult *result, |
55 | | GError **error); |
56 | | |
57 | | static void |
58 | | g_socket_address_enumerator_init (GSocketAddressEnumerator *enumerator) |
59 | 0 | { |
60 | 0 | } |
61 | | |
62 | | static void |
63 | | g_socket_address_enumerator_class_init (GSocketAddressEnumeratorClass *enumerator_class) |
64 | 0 | { |
65 | 0 | enumerator_class->next_async = g_socket_address_enumerator_real_next_async; |
66 | 0 | enumerator_class->next_finish = g_socket_address_enumerator_real_next_finish; |
67 | 0 | } |
68 | | |
69 | | /** |
70 | | * g_socket_address_enumerator_next: |
71 | | * @enumerator: a #GSocketAddressEnumerator |
72 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
73 | | * @error: a #GError. |
74 | | * |
75 | | * Retrieves the next #GSocketAddress from @enumerator. Note that this |
76 | | * may block for some amount of time. (Eg, a #GNetworkAddress may need |
77 | | * to do a DNS lookup before it can return an address.) Use |
78 | | * g_socket_address_enumerator_next_async() if you need to avoid |
79 | | * blocking. |
80 | | * |
81 | | * If @enumerator is expected to yield addresses, but for some reason |
82 | | * is unable to (eg, because of a DNS error), then the first call to |
83 | | * g_socket_address_enumerator_next() will return an appropriate error |
84 | | * in `*error`. However, if the first call to |
85 | | * g_socket_address_enumerator_next() succeeds, then any further |
86 | | * internal errors (other than @cancellable being triggered) will be |
87 | | * ignored. |
88 | | * |
89 | | * Returns: (transfer full) (nullable): a #GSocketAddress (owned by the caller), or %NULL on |
90 | | * error (in which case `*error` will be set) or if there are no |
91 | | * more addresses. |
92 | | */ |
93 | | GSocketAddress * |
94 | | g_socket_address_enumerator_next (GSocketAddressEnumerator *enumerator, |
95 | | GCancellable *cancellable, |
96 | | GError **error) |
97 | 0 | { |
98 | 0 | GSocketAddressEnumeratorClass *klass; |
99 | |
|
100 | 0 | g_return_val_if_fail (G_IS_SOCKET_ADDRESS_ENUMERATOR (enumerator), NULL); |
101 | | |
102 | 0 | klass = G_SOCKET_ADDRESS_ENUMERATOR_GET_CLASS (enumerator); |
103 | |
|
104 | 0 | return (* klass->next) (enumerator, cancellable, error); |
105 | 0 | } |
106 | | |
107 | | /* Default implementation just calls the synchronous method; this can |
108 | | * be used if the implementation already knows all of its addresses, |
109 | | * and so the synchronous method will never block. |
110 | | */ |
111 | | static void |
112 | | g_socket_address_enumerator_real_next_async (GSocketAddressEnumerator *enumerator, |
113 | | GCancellable *cancellable, |
114 | | GAsyncReadyCallback callback, |
115 | | gpointer user_data) |
116 | 0 | { |
117 | 0 | GTask *task; |
118 | 0 | GSocketAddress *address; |
119 | 0 | GError *error = NULL; |
120 | |
|
121 | 0 | task = g_task_new (enumerator, NULL, callback, user_data); |
122 | 0 | g_task_set_source_tag (task, g_socket_address_enumerator_real_next_async); |
123 | |
|
124 | 0 | address = g_socket_address_enumerator_next (enumerator, cancellable, &error); |
125 | 0 | if (error) |
126 | 0 | g_task_return_error (task, error); |
127 | 0 | else |
128 | 0 | g_task_return_pointer (task, address, g_object_unref); |
129 | |
|
130 | 0 | g_object_unref (task); |
131 | 0 | } |
132 | | |
133 | | /** |
134 | | * g_socket_address_enumerator_next_async: |
135 | | * @enumerator: a #GSocketAddressEnumerator |
136 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
137 | | * @callback: (scope async) (closure user_data): a #GAsyncReadyCallback to call |
138 | | * when the request is satisfied |
139 | | * @user_data: the data to pass to callback function |
140 | | * |
141 | | * Asynchronously retrieves the next #GSocketAddress from @enumerator |
142 | | * and then calls @callback, which must call |
143 | | * g_socket_address_enumerator_next_finish() to get the result. |
144 | | * |
145 | | * It is an error to call this multiple times before the previous callback has finished. |
146 | | */ |
147 | | void |
148 | | g_socket_address_enumerator_next_async (GSocketAddressEnumerator *enumerator, |
149 | | GCancellable *cancellable, |
150 | | GAsyncReadyCallback callback, |
151 | | gpointer user_data) |
152 | 0 | { |
153 | 0 | GSocketAddressEnumeratorClass *klass; |
154 | |
|
155 | 0 | g_return_if_fail (G_IS_SOCKET_ADDRESS_ENUMERATOR (enumerator)); |
156 | | |
157 | 0 | klass = G_SOCKET_ADDRESS_ENUMERATOR_GET_CLASS (enumerator); |
158 | |
|
159 | 0 | (* klass->next_async) (enumerator, cancellable, callback, user_data); |
160 | 0 | } |
161 | | |
162 | | static GSocketAddress * |
163 | | g_socket_address_enumerator_real_next_finish (GSocketAddressEnumerator *enumerator, |
164 | | GAsyncResult *result, |
165 | | GError **error) |
166 | 0 | { |
167 | 0 | g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL); |
168 | | |
169 | 0 | return g_task_propagate_pointer (G_TASK (result), error); |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * g_socket_address_enumerator_next_finish: |
174 | | * @enumerator: a #GSocketAddressEnumerator |
175 | | * @result: a #GAsyncResult |
176 | | * @error: a #GError |
177 | | * |
178 | | * Retrieves the result of a completed call to |
179 | | * g_socket_address_enumerator_next_async(). See |
180 | | * g_socket_address_enumerator_next() for more information about |
181 | | * error handling. |
182 | | * |
183 | | * Returns: (transfer full) (nullable): a #GSocketAddress (owned by the caller), or %NULL on |
184 | | * error (in which case `*error` will be set) or if there are no |
185 | | * more addresses. |
186 | | */ |
187 | | GSocketAddress * |
188 | | g_socket_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator, |
189 | | GAsyncResult *result, |
190 | | GError **error) |
191 | 0 | { |
192 | 0 | GSocketAddressEnumeratorClass *klass; |
193 | |
|
194 | 0 | g_return_val_if_fail (G_IS_SOCKET_ADDRESS_ENUMERATOR (enumerator), NULL); |
195 | | |
196 | 0 | klass = G_SOCKET_ADDRESS_ENUMERATOR_GET_CLASS (enumerator); |
197 | |
|
198 | 0 | return (* klass->next_finish) (enumerator, result, error); |
199 | 0 | } |