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