1 /* GNIO - GLib Network Layer of GIO
3 * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
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 of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Christian Kellner <gicmo@gnome.org>
21 * Samuel Cormier-Iijima <sciyoshi@gmail.com>
27 #include <gnio/gnio.h>
32 G_DEFINE_TYPE (GTcpClient, g_tcp_client, G_TYPE_OBJECT);
42 struct _GTcpClientPrivate
44 GInetSocketAddress *address;
51 g_tcp_client_constructed (GObject *object)
53 GTcpClient *client = G_TCP_CLIENT (object);
55 if (client->priv->address)
57 // we've been constructed with an address, extract hostname+port
58 client->priv->hostname = g_inet_address_to_string (g_inet_socket_address_get_address (client->priv->address));
59 client->priv->port = g_inet_socket_address_get_port (client->priv->address);
65 g_tcp_client_get_property (GObject *object,
70 GTcpClient *client = G_TCP_CLIENT (object);
75 g_value_set_object (value, client->priv->address);
79 g_value_set_string (value, client->priv->hostname);
83 g_value_set_uint (value, client->priv->port);
87 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92 g_tcp_client_set_property (GObject *object,
97 GTcpClient *client = G_TCP_CLIENT (object);
102 // sink the address' floating reference
103 client->priv->address = G_INET_SOCKET_ADDRESS (g_value_get_object (value));
104 if (client->priv->address)
105 g_object_ref_sink (client->priv->address);
109 client->priv->hostname = g_value_dup_string (value);
113 client->priv->port = g_value_get_uint (value);
117 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122 g_tcp_client_finalize (GObject *object)
124 GTcpClient *client = G_TCP_CLIENT (object);
126 g_object_unref (client->priv->address);
128 if (G_OBJECT_CLASS (g_tcp_client_parent_class)->finalize)
129 (*G_OBJECT_CLASS (g_tcp_client_parent_class)->finalize) (object);
133 g_tcp_client_dispose (GObject *object)
135 GTcpClient *client = G_TCP_CLIENT (object);
137 g_free (client->priv->hostname);
139 if (G_OBJECT_CLASS (g_tcp_client_parent_class)->dispose)
140 (*G_OBJECT_CLASS (g_tcp_client_parent_class)->dispose) (object);
144 g_tcp_client_class_init (GTcpClientClass *klass)
146 GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
148 g_type_class_add_private (klass, sizeof (GTcpClientPrivate));
150 gobject_class->finalize = g_tcp_client_finalize;
151 gobject_class->dispose = g_tcp_client_dispose;
152 gobject_class->constructed = g_tcp_client_constructed;
153 gobject_class->set_property = g_tcp_client_set_property;
154 gobject_class->get_property = g_tcp_client_get_property;
156 g_object_class_install_property (gobject_class, PROP_ADDRESS,
157 g_param_spec_object ("address",
159 "the remote address the socket will connect to",
160 G_TYPE_INET_SOCKET_ADDRESS,
161 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
163 g_object_class_install_property (gobject_class, PROP_HOSTNAME,
164 g_param_spec_string ("hostname",
166 "the hostname of the remote address the socket will connect to",
168 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
170 g_object_class_install_property (gobject_class, PROP_PORT,
171 g_param_spec_uint ("port",
173 "the remote port the socket will connect to",
177 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
181 g_tcp_client_init (GTcpClient *client)
183 client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, G_TYPE_TCP_CLIENT, GTcpClientPrivate);
185 client->priv->address = NULL;
186 client->priv->hostname = NULL;
187 client->priv->port = 0;
188 client->priv->socket = NULL;
192 g_tcp_client_new (const gchar *hostname,
195 return G_TCP_CLIENT (g_object_new (G_TYPE_TCP_CLIENT, "hostname", hostname, "port", port, NULL));
199 g_tcp_client_new_from_address (GInetSocketAddress *address)
201 return G_TCP_CLIENT (g_object_new (G_TYPE_TCP_CLIENT, "address", address, NULL));
204 GNetworkInputStream *
205 g_tcp_client_get_input_stream (GTcpClient *client)
207 if (!client->priv->socket)
210 return _g_network_input_stream_new (client->priv->socket);
213 GNetworkOutputStream *
214 g_tcp_client_get_output_stream (GTcpClient *client)
216 if (!client->priv->socket)
219 return _g_network_output_stream_new (client->priv->socket);
223 g_tcp_client_connect (GTcpClient *client,
224 GCancellable *cancellable,
227 GInetAddress *address;
229 g_return_val_if_fail (G_IS_TCP_CLIENT (client), FALSE);
231 if (!client->priv->address)
233 // we've been constructed with just hostname+port, resolve
234 GResolver *resolver = g_resolver_new ();
236 address = g_resolver_resolve (resolver, client->priv->hostname, cancellable, error);
241 client->priv->address = g_inet_socket_address_new (address, client->priv->port);
243 g_object_unref (resolver);
245 g_object_ref_sink (client->priv->address);
249 address = g_inet_socket_address_get_address (client->priv->address);
252 if (G_IS_INET4_ADDRESS (address))
253 client->priv->socket = g_socket_new (G_SOCKET_DOMAIN_INET, G_SOCKET_TYPE_STREAM, NULL, error);
254 else if (G_IS_INET6_ADDRESS (address))
255 client->priv->socket = g_socket_new (G_SOCKET_DOMAIN_INET6, G_SOCKET_TYPE_STREAM, NULL, error);
258 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported address domain");
262 if (!client->priv->socket)
265 if (g_cancellable_set_error_if_cancelled (cancellable, error))
268 if (!g_socket_connect (client->priv->socket, G_SOCKET_ADDRESS (client->priv->address), error))
275 GAsyncReadyCallback callback;
276 GCancellable *cancellable;
279 gchar address_buffer[256];
280 gsize address_length;
285 connect_callback (ConnectData *data,
286 GIOCondition condition,
294 g_tcp_client_connect_async (GTcpClient *client,
295 GCancellable *cancellable,
296 GAsyncReadyCallback callback,
303 g_tcp_client_connect_finish (GTcpClient *client,
304 GAsyncResult *result,
307 GSimpleAsyncResult *simple;
309 g_return_val_if_fail (G_IS_TCP_CLIENT (client), FALSE);
311 simple = G_SIMPLE_ASYNC_RESULT (result);
313 if (g_simple_async_result_propagate_error (simple, error))
316 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_tcp_client_connect_async);
322 g_tcp_client_close (GTcpClient *tcp_client)
324 g_return_if_fail (G_IS_TCP_CLIENT (tcp_client));