PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/gio/gsocketconnection.c

https://gitlab.com/ImageMagick/glib
C | 687 lines | 389 code | 99 blank | 199 comment | 28 complexity | 86606f2a90ef9bd6d4683d997d15b304 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0
  1. /* GIO - GLib Input, Output and Streaming Library
  2. *
  3. * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
  4. * © 2008 codethink
  5. * Copyright © 2009 Red Hat, Inc
  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. * Ryan Lortie <desrt@desrt.ca>
  23. * Alexander Larsson <alexl@redhat.com>
  24. */
  25. #include "config.h"
  26. #include "gsocketconnection.h"
  27. #include "gsocketoutputstream.h"
  28. #include "gsocketinputstream.h"
  29. #include "gioprivate.h"
  30. #include <gio/giostream.h>
  31. #include <gio/gtask.h>
  32. #include "gunixconnection.h"
  33. #include "gtcpconnection.h"
  34. #include "glibintl.h"
  35. /**
  36. * SECTION:gsocketconnection
  37. * @short_description: A socket connection
  38. * @include: gio/gio.h
  39. * @see_also: #GIOStream, #GSocketClient, #GSocketListener
  40. *
  41. * #GSocketConnection is a #GIOStream for a connected socket. They
  42. * can be created either by #GSocketClient when connecting to a host,
  43. * or by #GSocketListener when accepting a new client.
  44. *
  45. * The type of the #GSocketConnection object returned from these calls
  46. * depends on the type of the underlying socket that is in use. For
  47. * instance, for a TCP/IP connection it will be a #GTcpConnection.
  48. *
  49. * Choosing what type of object to construct is done with the socket
  50. * connection factory, and it is possible for 3rd parties to register
  51. * custom socket connection types for specific combination of socket
  52. * family/type/protocol using g_socket_connection_factory_register_type().
  53. *
  54. * To close a #GSocketConnection, use g_io_stream_close(). Closing both
  55. * substreams of the #GIOStream separately will not close the underlying
  56. * #GSocket.
  57. *
  58. * Since: 2.22
  59. */
  60. enum
  61. {
  62. PROP_NONE,
  63. PROP_SOCKET,
  64. };
  65. struct _GSocketConnectionPrivate
  66. {
  67. GSocket *socket;
  68. GInputStream *input_stream;
  69. GOutputStream *output_stream;
  70. GSocketAddress *cached_remote_address;
  71. gboolean in_dispose;
  72. };
  73. static gboolean g_socket_connection_close (GIOStream *stream,
  74. GCancellable *cancellable,
  75. GError **error);
  76. static void g_socket_connection_close_async (GIOStream *stream,
  77. int io_priority,
  78. GCancellable *cancellable,
  79. GAsyncReadyCallback callback,
  80. gpointer user_data);
  81. static gboolean g_socket_connection_close_finish (GIOStream *stream,
  82. GAsyncResult *result,
  83. GError **error);
  84. G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
  85. static GInputStream *
  86. g_socket_connection_get_input_stream (GIOStream *io_stream)
  87. {
  88. GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
  89. if (connection->priv->input_stream == NULL)
  90. connection->priv->input_stream = (GInputStream *)
  91. _g_socket_input_stream_new (connection->priv->socket);
  92. return connection->priv->input_stream;
  93. }
  94. static GOutputStream *
  95. g_socket_connection_get_output_stream (GIOStream *io_stream)
  96. {
  97. GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
  98. if (connection->priv->output_stream == NULL)
  99. connection->priv->output_stream = (GOutputStream *)
  100. _g_socket_output_stream_new (connection->priv->socket);
  101. return connection->priv->output_stream;
  102. }
  103. /**
  104. * g_socket_connection_is_connected:
  105. * @connection: a #GSocketConnection
  106. *
  107. * Checks if @connection is connected. This is equivalent to calling
  108. * g_socket_is_connected() on @connection's underlying #GSocket.
  109. *
  110. * Returns: whether @connection is connected
  111. *
  112. * Since: 2.32
  113. */
  114. gboolean
  115. g_socket_connection_is_connected (GSocketConnection *connection)
  116. {
  117. return g_socket_is_connected (connection->priv->socket);
  118. }
  119. /**
  120. * g_socket_connection_connect:
  121. * @connection: a #GSocketConnection
  122. * @address: a #GSocketAddress specifying the remote address.
  123. * @cancellable: (nullable): a %GCancellable or %NULL
  124. * @error: #GError for error reporting, or %NULL to ignore.
  125. *
  126. * Connect @connection to the specified remote address.
  127. *
  128. * Returns: %TRUE if the connection succeeded, %FALSE on error
  129. *
  130. * Since: 2.32
  131. */
  132. gboolean
  133. g_socket_connection_connect (GSocketConnection *connection,
  134. GSocketAddress *address,
  135. GCancellable *cancellable,
  136. GError **error)
  137. {
  138. g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
  139. g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
  140. return g_socket_connect (connection->priv->socket, address,
  141. cancellable, error);
  142. }
  143. static gboolean g_socket_connection_connect_callback (GSocket *socket,
  144. GIOCondition condition,
  145. gpointer user_data);
  146. /**
  147. * g_socket_connection_connect_async:
  148. * @connection: a #GSocketConnection
  149. * @address: a #GSocketAddress specifying the remote address.
  150. * @cancellable: (nullable): a %GCancellable or %NULL
  151. * @callback: (scope async): a #GAsyncReadyCallback
  152. * @user_data: (closure): user data for the callback
  153. *
  154. * Asynchronously connect @connection to the specified remote address.
  155. *
  156. * This clears the #GSocket:blocking flag on @connection's underlying
  157. * socket if it is currently set.
  158. *
  159. * Use g_socket_connection_connect_finish() to retrieve the result.
  160. *
  161. * Since: 2.32
  162. */
  163. void
  164. g_socket_connection_connect_async (GSocketConnection *connection,
  165. GSocketAddress *address,
  166. GCancellable *cancellable,
  167. GAsyncReadyCallback callback,
  168. gpointer user_data)
  169. {
  170. GTask *task;
  171. GError *tmp_error = NULL;
  172. g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
  173. g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
  174. task = g_task_new (connection, cancellable, callback, user_data);
  175. g_task_set_source_tag (task, g_socket_connection_connect_async);
  176. g_socket_set_blocking (connection->priv->socket, FALSE);
  177. if (g_socket_connect (connection->priv->socket, address,
  178. cancellable, &tmp_error))
  179. {
  180. g_task_return_boolean (task, TRUE);
  181. g_object_unref (task);
  182. }
  183. else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
  184. {
  185. GSource *source;
  186. g_error_free (tmp_error);
  187. source = g_socket_create_source (connection->priv->socket,
  188. G_IO_OUT, cancellable);
  189. g_task_attach_source (task, source,
  190. (GSourceFunc) g_socket_connection_connect_callback);
  191. g_source_unref (source);
  192. }
  193. else
  194. {
  195. g_task_return_error (task, tmp_error);
  196. g_object_unref (task);
  197. }
  198. }
  199. static gboolean
  200. g_socket_connection_connect_callback (GSocket *socket,
  201. GIOCondition condition,
  202. gpointer user_data)
  203. {
  204. GTask *task = user_data;
  205. GSocketConnection *connection = g_task_get_source_object (task);
  206. GError *error = NULL;
  207. if (g_socket_check_connect_result (connection->priv->socket, &error))
  208. g_task_return_boolean (task, TRUE);
  209. else
  210. g_task_return_error (task, error);
  211. g_object_unref (task);
  212. return FALSE;
  213. }
  214. /**
  215. * g_socket_connection_connect_finish:
  216. * @connection: a #GSocketConnection
  217. * @result: the #GAsyncResult
  218. * @error: #GError for error reporting, or %NULL to ignore.
  219. *
  220. * Gets the result of a g_socket_connection_connect_async() call.
  221. *
  222. * Returns: %TRUE if the connection succeeded, %FALSE on error
  223. *
  224. * Since: 2.32
  225. */
  226. gboolean
  227. g_socket_connection_connect_finish (GSocketConnection *connection,
  228. GAsyncResult *result,
  229. GError **error)
  230. {
  231. g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
  232. g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
  233. return g_task_propagate_boolean (G_TASK (result), error);
  234. }
  235. /**
  236. * g_socket_connection_get_socket:
  237. * @connection: a #GSocketConnection
  238. *
  239. * Gets the underlying #GSocket object of the connection.
  240. * This can be useful if you want to do something unusual on it
  241. * not supported by the #GSocketConnection APIs.
  242. *
  243. * Returns: (transfer none): a #GSocket or %NULL on error.
  244. *
  245. * Since: 2.22
  246. */
  247. GSocket *
  248. g_socket_connection_get_socket (GSocketConnection *connection)
  249. {
  250. g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
  251. return connection->priv->socket;
  252. }
  253. /**
  254. * g_socket_connection_get_local_address:
  255. * @connection: a #GSocketConnection
  256. * @error: #GError for error reporting, or %NULL to ignore.
  257. *
  258. * Try to get the local address of a socket connection.
  259. *
  260. * Returns: (transfer full): a #GSocketAddress or %NULL on error.
  261. * Free the returned object with g_object_unref().
  262. *
  263. * Since: 2.22
  264. */
  265. GSocketAddress *
  266. g_socket_connection_get_local_address (GSocketConnection *connection,
  267. GError **error)
  268. {
  269. return g_socket_get_local_address (connection->priv->socket, error);
  270. }
  271. /**
  272. * g_socket_connection_get_remote_address:
  273. * @connection: a #GSocketConnection
  274. * @error: #GError for error reporting, or %NULL to ignore.
  275. *
  276. * Try to get the remote address of a socket connection.
  277. *
  278. * Since GLib 2.40, when used with g_socket_client_connect() or
  279. * g_socket_client_connect_async(), during emission of
  280. * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
  281. * address that will be used for the connection. This allows
  282. * applications to print e.g. "Connecting to example.com
  283. * (10.42.77.3)...".
  284. *
  285. * Returns: (transfer full): a #GSocketAddress or %NULL on error.
  286. * Free the returned object with g_object_unref().
  287. *
  288. * Since: 2.22
  289. */
  290. GSocketAddress *
  291. g_socket_connection_get_remote_address (GSocketConnection *connection,
  292. GError **error)
  293. {
  294. if (!g_socket_is_connected (connection->priv->socket))
  295. {
  296. return connection->priv->cached_remote_address ?
  297. g_object_ref (connection->priv->cached_remote_address) : NULL;
  298. }
  299. return g_socket_get_remote_address (connection->priv->socket, error);
  300. }
  301. /* Private API allowing applications to retrieve the resolved address
  302. * now, before we start connecting.
  303. *
  304. * https://bugzilla.gnome.org/show_bug.cgi?id=712547
  305. */
  306. void
  307. g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
  308. GSocketAddress *address)
  309. {
  310. g_clear_object (&connection->priv->cached_remote_address);
  311. connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
  312. }
  313. static void
  314. g_socket_connection_get_property (GObject *object,
  315. guint prop_id,
  316. GValue *value,
  317. GParamSpec *pspec)
  318. {
  319. GSocketConnection *connection = G_SOCKET_CONNECTION (object);
  320. switch (prop_id)
  321. {
  322. case PROP_SOCKET:
  323. g_value_set_object (value, connection->priv->socket);
  324. break;
  325. default:
  326. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  327. }
  328. }
  329. static void
  330. g_socket_connection_set_property (GObject *object,
  331. guint prop_id,
  332. const GValue *value,
  333. GParamSpec *pspec)
  334. {
  335. GSocketConnection *connection = G_SOCKET_CONNECTION (object);
  336. switch (prop_id)
  337. {
  338. case PROP_SOCKET:
  339. connection->priv->socket = G_SOCKET (g_value_dup_object (value));
  340. break;
  341. default:
  342. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  343. }
  344. }
  345. static void
  346. g_socket_connection_constructed (GObject *object)
  347. {
  348. GSocketConnection *connection = G_SOCKET_CONNECTION (object);
  349. g_assert (connection->priv->socket != NULL);
  350. }
  351. static void
  352. g_socket_connection_dispose (GObject *object)
  353. {
  354. GSocketConnection *connection = G_SOCKET_CONNECTION (object);
  355. connection->priv->in_dispose = TRUE;
  356. g_clear_object (&connection->priv->cached_remote_address);
  357. G_OBJECT_CLASS (g_socket_connection_parent_class)
  358. ->dispose (object);
  359. connection->priv->in_dispose = FALSE;
  360. }
  361. static void
  362. g_socket_connection_finalize (GObject *object)
  363. {
  364. GSocketConnection *connection = G_SOCKET_CONNECTION (object);
  365. if (connection->priv->input_stream)
  366. g_object_unref (connection->priv->input_stream);
  367. if (connection->priv->output_stream)
  368. g_object_unref (connection->priv->output_stream);
  369. g_object_unref (connection->priv->socket);
  370. G_OBJECT_CLASS (g_socket_connection_parent_class)
  371. ->finalize (object);
  372. }
  373. static void
  374. g_socket_connection_class_init (GSocketConnectionClass *klass)
  375. {
  376. GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  377. GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
  378. gobject_class->set_property = g_socket_connection_set_property;
  379. gobject_class->get_property = g_socket_connection_get_property;
  380. gobject_class->constructed = g_socket_connection_constructed;
  381. gobject_class->finalize = g_socket_connection_finalize;
  382. gobject_class->dispose = g_socket_connection_dispose;
  383. stream_class->get_input_stream = g_socket_connection_get_input_stream;
  384. stream_class->get_output_stream = g_socket_connection_get_output_stream;
  385. stream_class->close_fn = g_socket_connection_close;
  386. stream_class->close_async = g_socket_connection_close_async;
  387. stream_class->close_finish = g_socket_connection_close_finish;
  388. g_object_class_install_property (gobject_class,
  389. PROP_SOCKET,
  390. g_param_spec_object ("socket",
  391. P_("Socket"),
  392. P_("The underlying GSocket"),
  393. G_TYPE_SOCKET,
  394. G_PARAM_CONSTRUCT_ONLY |
  395. G_PARAM_READWRITE |
  396. G_PARAM_STATIC_STRINGS));
  397. }
  398. static void
  399. g_socket_connection_init (GSocketConnection *connection)
  400. {
  401. connection->priv = g_socket_connection_get_instance_private (connection);
  402. }
  403. static gboolean
  404. g_socket_connection_close (GIOStream *stream,
  405. GCancellable *cancellable,
  406. GError **error)
  407. {
  408. GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
  409. if (connection->priv->output_stream)
  410. g_output_stream_close (connection->priv->output_stream,
  411. cancellable, NULL);
  412. if (connection->priv->input_stream)
  413. g_input_stream_close (connection->priv->input_stream,
  414. cancellable, NULL);
  415. /* Don't close the underlying socket if this is being called
  416. * as part of dispose(); when destroying the GSocketConnection,
  417. * we only want to close the socket if we're holding the last
  418. * reference on it, and in that case it will close itself when
  419. * we unref it in finalize().
  420. */
  421. if (connection->priv->in_dispose)
  422. return TRUE;
  423. return g_socket_close (connection->priv->socket, error);
  424. }
  425. static void
  426. g_socket_connection_close_async (GIOStream *stream,
  427. int io_priority,
  428. GCancellable *cancellable,
  429. GAsyncReadyCallback callback,
  430. gpointer user_data)
  431. {
  432. GTask *task;
  433. GIOStreamClass *class;
  434. GError *error;
  435. class = G_IO_STREAM_GET_CLASS (stream);
  436. task = g_task_new (stream, cancellable, callback, user_data);
  437. g_task_set_source_tag (task, g_socket_connection_close_async);
  438. /* socket close is not blocked, just do it! */
  439. error = NULL;
  440. if (class->close_fn &&
  441. !class->close_fn (stream, cancellable, &error))
  442. g_task_return_error (task, error);
  443. else
  444. g_task_return_boolean (task, TRUE);
  445. g_object_unref (task);
  446. }
  447. static gboolean
  448. g_socket_connection_close_finish (GIOStream *stream,
  449. GAsyncResult *result,
  450. GError **error)
  451. {
  452. return g_task_propagate_boolean (G_TASK (result), error);
  453. }
  454. typedef struct {
  455. GSocketFamily socket_family;
  456. GSocketType socket_type;
  457. int protocol;
  458. GType implementation;
  459. } ConnectionFactory;
  460. static guint
  461. connection_factory_hash (gconstpointer key)
  462. {
  463. const ConnectionFactory *factory = key;
  464. guint h;
  465. h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
  466. /* This is likely to be small, so spread over whole
  467. hash space to get some distribution */
  468. h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
  469. return h;
  470. }
  471. static gboolean
  472. connection_factory_equal (gconstpointer _a,
  473. gconstpointer _b)
  474. {
  475. const ConnectionFactory *a = _a;
  476. const ConnectionFactory *b = _b;
  477. if (a->socket_family != b->socket_family)
  478. return FALSE;
  479. if (a->socket_type != b->socket_type)
  480. return FALSE;
  481. if (a->protocol != b->protocol)
  482. return FALSE;
  483. return TRUE;
  484. }
  485. static GHashTable *connection_factories = NULL;
  486. G_LOCK_DEFINE_STATIC(connection_factories);
  487. /**
  488. * g_socket_connection_factory_register_type:
  489. * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
  490. * @family: a #GSocketFamily
  491. * @type: a #GSocketType
  492. * @protocol: a protocol id
  493. *
  494. * Looks up the #GType to be used when creating socket connections on
  495. * sockets with the specified @family, @type and @protocol.
  496. *
  497. * If no type is registered, the #GSocketConnection base type is returned.
  498. *
  499. * Since: 2.22
  500. */
  501. void
  502. g_socket_connection_factory_register_type (GType g_type,
  503. GSocketFamily family,
  504. GSocketType type,
  505. gint protocol)
  506. {
  507. ConnectionFactory *factory;
  508. g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
  509. G_LOCK (connection_factories);
  510. if (connection_factories == NULL)
  511. connection_factories = g_hash_table_new_full (connection_factory_hash,
  512. connection_factory_equal,
  513. (GDestroyNotify)g_free,
  514. NULL);
  515. factory = g_new0 (ConnectionFactory, 1);
  516. factory->socket_family = family;
  517. factory->socket_type = type;
  518. factory->protocol = protocol;
  519. factory->implementation = g_type;
  520. g_hash_table_insert (connection_factories,
  521. factory, factory);
  522. G_UNLOCK (connection_factories);
  523. }
  524. static void
  525. init_builtin_types (void)
  526. {
  527. #ifndef G_OS_WIN32
  528. g_type_ensure (G_TYPE_UNIX_CONNECTION);
  529. #endif
  530. g_type_ensure (G_TYPE_TCP_CONNECTION);
  531. }
  532. /**
  533. * g_socket_connection_factory_lookup_type:
  534. * @family: a #GSocketFamily
  535. * @type: a #GSocketType
  536. * @protocol_id: a protocol id
  537. *
  538. * Looks up the #GType to be used when creating socket connections on
  539. * sockets with the specified @family, @type and @protocol_id.
  540. *
  541. * If no type is registered, the #GSocketConnection base type is returned.
  542. *
  543. * Returns: a #GType
  544. *
  545. * Since: 2.22
  546. */
  547. GType
  548. g_socket_connection_factory_lookup_type (GSocketFamily family,
  549. GSocketType type,
  550. gint protocol_id)
  551. {
  552. ConnectionFactory *factory, key;
  553. GType g_type;
  554. init_builtin_types ();
  555. G_LOCK (connection_factories);
  556. g_type = G_TYPE_SOCKET_CONNECTION;
  557. if (connection_factories)
  558. {
  559. key.socket_family = family;
  560. key.socket_type = type;
  561. key.protocol = protocol_id;
  562. factory = g_hash_table_lookup (connection_factories, &key);
  563. if (factory)
  564. g_type = factory->implementation;
  565. }
  566. G_UNLOCK (connection_factories);
  567. return g_type;
  568. }
  569. /**
  570. * g_socket_connection_factory_create_connection:
  571. * @socket: a #GSocket
  572. *
  573. * Creates a #GSocketConnection subclass of the right type for
  574. * @socket.
  575. *
  576. * Returns: (transfer full): a #GSocketConnection
  577. *
  578. * Since: 2.22
  579. */
  580. GSocketConnection *
  581. g_socket_connection_factory_create_connection (GSocket *socket)
  582. {
  583. GType type;
  584. type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
  585. g_socket_get_socket_type (socket),
  586. g_socket_get_protocol (socket));
  587. return g_object_new (type, "socket", socket, NULL);
  588. }