PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/gio/gdbusprivate.c

https://gitlab.com/ImageMagick/glib
C | 2234 lines | 1624 code | 311 blank | 299 comment | 217 complexity | c0d699e6a401d4298dd1c459906c3dc7 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /* GDBus - GLib D-Bus Library
  2. *
  3. * Copyright (C) 2008-2010 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. * Author: David Zeuthen <davidz@redhat.com>
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "giotypes.h"
  24. #include "gioenumtypes.h"
  25. #include "gsocket.h"
  26. #include "gdbusauthobserver.h"
  27. #include "gdbusprivate.h"
  28. #include "gdbusmessage.h"
  29. #include "gdbusconnection.h"
  30. #include "gdbusproxy.h"
  31. #include "gdbuserror.h"
  32. #include "gdbusintrospection.h"
  33. #include "gtask.h"
  34. #include "ginputstream.h"
  35. #include "gmemoryinputstream.h"
  36. #include "giostream.h"
  37. #include "glib/gstdio.h"
  38. #include "gsocketaddress.h"
  39. #include "gsocketcontrolmessage.h"
  40. #include "gsocketconnection.h"
  41. #include "gsocketoutputstream.h"
  42. #ifdef G_OS_UNIX
  43. #include "gunixfdmessage.h"
  44. #include "gunixconnection.h"
  45. #include "gunixcredentialsmessage.h"
  46. #endif
  47. #ifdef G_OS_WIN32
  48. #include <windows.h>
  49. #endif
  50. #include "glibintl.h"
  51. static gboolean _g_dbus_worker_do_initial_read (gpointer data);
  52. static void schedule_pending_close (GDBusWorker *worker);
  53. /* ---------------------------------------------------------------------------------------------------- */
  54. gchar *
  55. _g_dbus_hexdump (const gchar *data, gsize len, guint indent)
  56. {
  57. guint n, m;
  58. GString *ret;
  59. ret = g_string_new (NULL);
  60. for (n = 0; n < len; n += 16)
  61. {
  62. g_string_append_printf (ret, "%*s%04x: ", indent, "", n);
  63. for (m = n; m < n + 16; m++)
  64. {
  65. if (m > n && (m%4) == 0)
  66. g_string_append_c (ret, ' ');
  67. if (m < len)
  68. g_string_append_printf (ret, "%02x ", (guchar) data[m]);
  69. else
  70. g_string_append (ret, " ");
  71. }
  72. g_string_append (ret, " ");
  73. for (m = n; m < len && m < n + 16; m++)
  74. g_string_append_c (ret, g_ascii_isprint (data[m]) ? data[m] : '.');
  75. g_string_append_c (ret, '\n');
  76. }
  77. return g_string_free (ret, FALSE);
  78. }
  79. /* ---------------------------------------------------------------------------------------------------- */
  80. /* Unfortunately ancillary messages are discarded when reading from a
  81. * socket using the GSocketInputStream abstraction. So we provide a
  82. * very GInputStream-ish API that uses GSocket in this case (very
  83. * similar to GSocketInputStream).
  84. */
  85. typedef struct
  86. {
  87. void *buffer;
  88. gsize count;
  89. GSocketControlMessage ***messages;
  90. gint *num_messages;
  91. } ReadWithControlData;
  92. static void
  93. read_with_control_data_free (ReadWithControlData *data)
  94. {
  95. g_slice_free (ReadWithControlData, data);
  96. }
  97. static gboolean
  98. _g_socket_read_with_control_messages_ready (GSocket *socket,
  99. GIOCondition condition,
  100. gpointer user_data)
  101. {
  102. GTask *task = user_data;
  103. ReadWithControlData *data = g_task_get_task_data (task);
  104. GError *error;
  105. gssize result;
  106. GInputVector vector;
  107. error = NULL;
  108. vector.buffer = data->buffer;
  109. vector.size = data->count;
  110. result = g_socket_receive_message (socket,
  111. NULL, /* address */
  112. &vector,
  113. 1,
  114. data->messages,
  115. data->num_messages,
  116. NULL,
  117. g_task_get_cancellable (task),
  118. &error);
  119. if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
  120. {
  121. g_error_free (error);
  122. return TRUE;
  123. }
  124. g_assert (result >= 0 || error != NULL);
  125. if (result >= 0)
  126. g_task_return_int (task, result);
  127. else
  128. g_task_return_error (task, error);
  129. g_object_unref (task);
  130. return FALSE;
  131. }
  132. static void
  133. _g_socket_read_with_control_messages (GSocket *socket,
  134. void *buffer,
  135. gsize count,
  136. GSocketControlMessage ***messages,
  137. gint *num_messages,
  138. gint io_priority,
  139. GCancellable *cancellable,
  140. GAsyncReadyCallback callback,
  141. gpointer user_data)
  142. {
  143. GTask *task;
  144. ReadWithControlData *data;
  145. GSource *source;
  146. data = g_slice_new0 (ReadWithControlData);
  147. data->buffer = buffer;
  148. data->count = count;
  149. data->messages = messages;
  150. data->num_messages = num_messages;
  151. task = g_task_new (socket, cancellable, callback, user_data);
  152. g_task_set_source_tag (task, _g_socket_read_with_control_messages);
  153. g_task_set_task_data (task, data, (GDestroyNotify) read_with_control_data_free);
  154. if (g_socket_condition_check (socket, G_IO_IN))
  155. {
  156. if (!_g_socket_read_with_control_messages_ready (socket, G_IO_IN, task))
  157. return;
  158. }
  159. source = g_socket_create_source (socket,
  160. G_IO_IN | G_IO_HUP | G_IO_ERR,
  161. cancellable);
  162. g_task_attach_source (task, source, (GSourceFunc) _g_socket_read_with_control_messages_ready);
  163. g_source_unref (source);
  164. }
  165. static gssize
  166. _g_socket_read_with_control_messages_finish (GSocket *socket,
  167. GAsyncResult *result,
  168. GError **error)
  169. {
  170. g_return_val_if_fail (G_IS_SOCKET (socket), -1);
  171. g_return_val_if_fail (g_task_is_valid (result, socket), -1);
  172. return g_task_propagate_int (G_TASK (result), error);
  173. }
  174. /* ---------------------------------------------------------------------------------------------------- */
  175. /* Work-around for https://bugzilla.gnome.org/show_bug.cgi?id=674885
  176. and see also the original https://bugzilla.gnome.org/show_bug.cgi?id=627724 */
  177. static GPtrArray *ensured_classes = NULL;
  178. static void
  179. ensure_type (GType gtype)
  180. {
  181. g_ptr_array_add (ensured_classes, g_type_class_ref (gtype));
  182. }
  183. static void
  184. release_required_types (void)
  185. {
  186. g_ptr_array_foreach (ensured_classes, (GFunc) g_type_class_unref, NULL);
  187. g_ptr_array_unref (ensured_classes);
  188. ensured_classes = NULL;
  189. }
  190. static void
  191. ensure_required_types (void)
  192. {
  193. g_assert (ensured_classes == NULL);
  194. ensured_classes = g_ptr_array_new ();
  195. /* Generally in this list, you should initialize types which are used as
  196. * properties first, then the class which has them. For example, GDBusProxy
  197. * has a type of GDBusConnection, so we initialize GDBusConnection first.
  198. * And because GDBusConnection has a property of type GDBusConnectionFlags,
  199. * we initialize that first.
  200. *
  201. * Similarly, GSocket has a type of GSocketAddress.
  202. *
  203. * We don't fill out the whole dependency tree right now because in practice
  204. * it tends to be just types that GDBus use that cause pain, and there
  205. * is work on a more general approach in https://bugzilla.gnome.org/show_bug.cgi?id=674885
  206. */
  207. ensure_type (G_TYPE_TASK);
  208. ensure_type (G_TYPE_MEMORY_INPUT_STREAM);
  209. ensure_type (G_TYPE_DBUS_CONNECTION_FLAGS);
  210. ensure_type (G_TYPE_DBUS_CAPABILITY_FLAGS);
  211. ensure_type (G_TYPE_DBUS_AUTH_OBSERVER);
  212. ensure_type (G_TYPE_DBUS_CONNECTION);
  213. ensure_type (G_TYPE_DBUS_PROXY);
  214. ensure_type (G_TYPE_SOCKET_FAMILY);
  215. ensure_type (G_TYPE_SOCKET_TYPE);
  216. ensure_type (G_TYPE_SOCKET_PROTOCOL);
  217. ensure_type (G_TYPE_SOCKET_ADDRESS);
  218. ensure_type (G_TYPE_SOCKET);
  219. }
  220. /* ---------------------------------------------------------------------------------------------------- */
  221. typedef struct
  222. {
  223. volatile gint refcount;
  224. GThread *thread;
  225. GMainContext *context;
  226. GMainLoop *loop;
  227. } SharedThreadData;
  228. static gpointer
  229. gdbus_shared_thread_func (gpointer user_data)
  230. {
  231. SharedThreadData *data = user_data;
  232. g_main_context_push_thread_default (data->context);
  233. g_main_loop_run (data->loop);
  234. g_main_context_pop_thread_default (data->context);
  235. release_required_types ();
  236. return NULL;
  237. }
  238. /* ---------------------------------------------------------------------------------------------------- */
  239. static SharedThreadData *
  240. _g_dbus_shared_thread_ref (void)
  241. {
  242. static gsize shared_thread_data = 0;
  243. SharedThreadData *ret;
  244. if (g_once_init_enter (&shared_thread_data))
  245. {
  246. SharedThreadData *data;
  247. data = g_new0 (SharedThreadData, 1);
  248. data->refcount = 0;
  249. data->context = g_main_context_new ();
  250. data->loop = g_main_loop_new (data->context, FALSE);
  251. data->thread = g_thread_new ("gdbus",
  252. gdbus_shared_thread_func,
  253. data);
  254. /* We can cast between gsize and gpointer safely */
  255. g_once_init_leave (&shared_thread_data, (gsize) data);
  256. }
  257. ret = (SharedThreadData*) shared_thread_data;
  258. g_atomic_int_inc (&ret->refcount);
  259. return ret;
  260. }
  261. static void
  262. _g_dbus_shared_thread_unref (SharedThreadData *data)
  263. {
  264. /* TODO: actually destroy the shared thread here */
  265. #if 0
  266. g_assert (data != NULL);
  267. if (g_atomic_int_dec_and_test (&data->refcount))
  268. {
  269. g_main_loop_quit (data->loop);
  270. //g_thread_join (data->thread);
  271. g_main_loop_unref (data->loop);
  272. g_main_context_unref (data->context);
  273. }
  274. #endif
  275. }
  276. /* ---------------------------------------------------------------------------------------------------- */
  277. typedef enum {
  278. PENDING_NONE = 0,
  279. PENDING_WRITE,
  280. PENDING_FLUSH,
  281. PENDING_CLOSE
  282. } OutputPending;
  283. struct GDBusWorker
  284. {
  285. volatile gint ref_count;
  286. SharedThreadData *shared_thread_data;
  287. /* really a boolean, but GLib 2.28 lacks atomic boolean ops */
  288. volatile gint stopped;
  289. /* TODO: frozen (e.g. G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) currently
  290. * only affects messages received from the other peer (since GDBusServer is the
  291. * only user) - we might want it to affect messages sent to the other peer too?
  292. */
  293. gboolean frozen;
  294. GDBusCapabilityFlags capabilities;
  295. GQueue *received_messages_while_frozen;
  296. GIOStream *stream;
  297. GCancellable *cancellable;
  298. GDBusWorkerMessageReceivedCallback message_received_callback;
  299. GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback;
  300. GDBusWorkerDisconnectedCallback disconnected_callback;
  301. gpointer user_data;
  302. /* if not NULL, stream is GSocketConnection */
  303. GSocket *socket;
  304. /* used for reading */
  305. GMutex read_lock;
  306. gchar *read_buffer;
  307. gsize read_buffer_allocated_size;
  308. gsize read_buffer_cur_size;
  309. gsize read_buffer_bytes_wanted;
  310. GUnixFDList *read_fd_list;
  311. GSocketControlMessage **read_ancillary_messages;
  312. gint read_num_ancillary_messages;
  313. /* Whether an async write, flush or close, or none of those, is pending.
  314. * Only the worker thread may change its value, and only with the write_lock.
  315. * Other threads may read its value when holding the write_lock.
  316. * The worker thread may read its value at any time.
  317. */
  318. OutputPending output_pending;
  319. /* used for writing */
  320. GMutex write_lock;
  321. /* queue of MessageToWriteData, protected by write_lock */
  322. GQueue *write_queue;
  323. /* protected by write_lock */
  324. guint64 write_num_messages_written;
  325. /* number of messages we'd written out last time we flushed;
  326. * protected by write_lock
  327. */
  328. guint64 write_num_messages_flushed;
  329. /* list of FlushData, protected by write_lock */
  330. GList *write_pending_flushes;
  331. /* list of CloseData, protected by write_lock */
  332. GList *pending_close_attempts;
  333. /* no lock - only used from the worker thread */
  334. gboolean close_expected;
  335. };
  336. static void _g_dbus_worker_unref (GDBusWorker *worker);
  337. /* ---------------------------------------------------------------------------------------------------- */
  338. typedef struct
  339. {
  340. GMutex mutex;
  341. GCond cond;
  342. guint64 number_to_wait_for;
  343. GError *error;
  344. } FlushData;
  345. struct _MessageToWriteData ;
  346. typedef struct _MessageToWriteData MessageToWriteData;
  347. static void message_to_write_data_free (MessageToWriteData *data);
  348. static void read_message_print_transport_debug (gssize bytes_read,
  349. GDBusWorker *worker);
  350. static void write_message_print_transport_debug (gssize bytes_written,
  351. MessageToWriteData *data);
  352. typedef struct {
  353. GDBusWorker *worker;
  354. GTask *task;
  355. } CloseData;
  356. static void close_data_free (CloseData *close_data)
  357. {
  358. g_clear_object (&close_data->task);
  359. _g_dbus_worker_unref (close_data->worker);
  360. g_slice_free (CloseData, close_data);
  361. }
  362. /* ---------------------------------------------------------------------------------------------------- */
  363. static GDBusWorker *
  364. _g_dbus_worker_ref (GDBusWorker *worker)
  365. {
  366. g_atomic_int_inc (&worker->ref_count);
  367. return worker;
  368. }
  369. static void
  370. _g_dbus_worker_unref (GDBusWorker *worker)
  371. {
  372. if (g_atomic_int_dec_and_test (&worker->ref_count))
  373. {
  374. g_assert (worker->write_pending_flushes == NULL);
  375. _g_dbus_shared_thread_unref (worker->shared_thread_data);
  376. g_object_unref (worker->stream);
  377. g_mutex_clear (&worker->read_lock);
  378. g_object_unref (worker->cancellable);
  379. if (worker->read_fd_list != NULL)
  380. g_object_unref (worker->read_fd_list);
  381. g_queue_free_full (worker->received_messages_while_frozen, (GDestroyNotify) g_object_unref);
  382. g_mutex_clear (&worker->write_lock);
  383. g_queue_free_full (worker->write_queue, (GDestroyNotify) message_to_write_data_free);
  384. g_free (worker->read_buffer);
  385. g_free (worker);
  386. }
  387. }
  388. static void
  389. _g_dbus_worker_emit_disconnected (GDBusWorker *worker,
  390. gboolean remote_peer_vanished,
  391. GError *error)
  392. {
  393. if (!g_atomic_int_get (&worker->stopped))
  394. worker->disconnected_callback (worker, remote_peer_vanished, error, worker->user_data);
  395. }
  396. static void
  397. _g_dbus_worker_emit_message_received (GDBusWorker *worker,
  398. GDBusMessage *message)
  399. {
  400. if (!g_atomic_int_get (&worker->stopped))
  401. worker->message_received_callback (worker, message, worker->user_data);
  402. }
  403. static GDBusMessage *
  404. _g_dbus_worker_emit_message_about_to_be_sent (GDBusWorker *worker,
  405. GDBusMessage *message)
  406. {
  407. GDBusMessage *ret;
  408. if (!g_atomic_int_get (&worker->stopped))
  409. ret = worker->message_about_to_be_sent_callback (worker, message, worker->user_data);
  410. else
  411. ret = message;
  412. return ret;
  413. }
  414. /* can only be called from private thread with read-lock held - takes ownership of @message */
  415. static void
  416. _g_dbus_worker_queue_or_deliver_received_message (GDBusWorker *worker,
  417. GDBusMessage *message)
  418. {
  419. if (worker->frozen || g_queue_get_length (worker->received_messages_while_frozen) > 0)
  420. {
  421. /* queue up */
  422. g_queue_push_tail (worker->received_messages_while_frozen, message);
  423. }
  424. else
  425. {
  426. /* not frozen, nor anything in queue */
  427. _g_dbus_worker_emit_message_received (worker, message);
  428. g_object_unref (message);
  429. }
  430. }
  431. /* called in private thread shared by all GDBusConnection instances (without read-lock held) */
  432. static gboolean
  433. unfreeze_in_idle_cb (gpointer user_data)
  434. {
  435. GDBusWorker *worker = user_data;
  436. GDBusMessage *message;
  437. g_mutex_lock (&worker->read_lock);
  438. if (worker->frozen)
  439. {
  440. while ((message = g_queue_pop_head (worker->received_messages_while_frozen)) != NULL)
  441. {
  442. _g_dbus_worker_emit_message_received (worker, message);
  443. g_object_unref (message);
  444. }
  445. worker->frozen = FALSE;
  446. }
  447. else
  448. {
  449. g_assert (g_queue_get_length (worker->received_messages_while_frozen) == 0);
  450. }
  451. g_mutex_unlock (&worker->read_lock);
  452. return FALSE;
  453. }
  454. /* can be called from any thread */
  455. void
  456. _g_dbus_worker_unfreeze (GDBusWorker *worker)
  457. {
  458. GSource *idle_source;
  459. idle_source = g_idle_source_new ();
  460. g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
  461. g_source_set_callback (idle_source,
  462. unfreeze_in_idle_cb,
  463. _g_dbus_worker_ref (worker),
  464. (GDestroyNotify) _g_dbus_worker_unref);
  465. g_source_set_name (idle_source, "[gio] unfreeze_in_idle_cb");
  466. g_source_attach (idle_source, worker->shared_thread_data->context);
  467. g_source_unref (idle_source);
  468. }
  469. /* ---------------------------------------------------------------------------------------------------- */
  470. static void _g_dbus_worker_do_read_unlocked (GDBusWorker *worker);
  471. /* called in private thread shared by all GDBusConnection instances (without read-lock held) */
  472. static void
  473. _g_dbus_worker_do_read_cb (GInputStream *input_stream,
  474. GAsyncResult *res,
  475. gpointer user_data)
  476. {
  477. GDBusWorker *worker = user_data;
  478. GError *error;
  479. gssize bytes_read;
  480. g_mutex_lock (&worker->read_lock);
  481. /* If already stopped, don't even process the reply */
  482. if (g_atomic_int_get (&worker->stopped))
  483. goto out;
  484. error = NULL;
  485. if (worker->socket == NULL)
  486. bytes_read = g_input_stream_read_finish (g_io_stream_get_input_stream (worker->stream),
  487. res,
  488. &error);
  489. else
  490. bytes_read = _g_socket_read_with_control_messages_finish (worker->socket,
  491. res,
  492. &error);
  493. if (worker->read_num_ancillary_messages > 0)
  494. {
  495. gint n;
  496. for (n = 0; n < worker->read_num_ancillary_messages; n++)
  497. {
  498. GSocketControlMessage *control_message = G_SOCKET_CONTROL_MESSAGE (worker->read_ancillary_messages[n]);
  499. if (FALSE)
  500. {
  501. }
  502. #ifdef G_OS_UNIX
  503. else if (G_IS_UNIX_FD_MESSAGE (control_message))
  504. {
  505. GUnixFDMessage *fd_message;
  506. gint *fds;
  507. gint num_fds;
  508. fd_message = G_UNIX_FD_MESSAGE (control_message);
  509. fds = g_unix_fd_message_steal_fds (fd_message, &num_fds);
  510. if (worker->read_fd_list == NULL)
  511. {
  512. worker->read_fd_list = g_unix_fd_list_new_from_array (fds, num_fds);
  513. }
  514. else
  515. {
  516. gint n;
  517. for (n = 0; n < num_fds; n++)
  518. {
  519. /* TODO: really want a append_steal() */
  520. g_unix_fd_list_append (worker->read_fd_list, fds[n], NULL);
  521. (void) g_close (fds[n], NULL);
  522. }
  523. }
  524. g_free (fds);
  525. }
  526. else if (G_IS_UNIX_CREDENTIALS_MESSAGE (control_message))
  527. {
  528. /* do nothing */
  529. }
  530. #endif
  531. else
  532. {
  533. if (error == NULL)
  534. {
  535. g_set_error (&error,
  536. G_IO_ERROR,
  537. G_IO_ERROR_FAILED,
  538. "Unexpected ancillary message of type %s received from peer",
  539. g_type_name (G_TYPE_FROM_INSTANCE (control_message)));
  540. _g_dbus_worker_emit_disconnected (worker, TRUE, error);
  541. g_error_free (error);
  542. g_object_unref (control_message);
  543. n++;
  544. while (n < worker->read_num_ancillary_messages)
  545. g_object_unref (worker->read_ancillary_messages[n++]);
  546. g_free (worker->read_ancillary_messages);
  547. goto out;
  548. }
  549. }
  550. g_object_unref (control_message);
  551. }
  552. g_free (worker->read_ancillary_messages);
  553. }
  554. if (bytes_read == -1)
  555. {
  556. if (G_UNLIKELY (_g_dbus_debug_transport ()))
  557. {
  558. _g_dbus_debug_print_lock ();
  559. g_print ("========================================================================\n"
  560. "GDBus-debug:Transport:\n"
  561. " ---- READ ERROR on stream of type %s:\n"
  562. " ---- %s %d: %s\n",
  563. g_type_name (G_TYPE_FROM_INSTANCE (g_io_stream_get_input_stream (worker->stream))),
  564. g_quark_to_string (error->domain), error->code,
  565. error->message);
  566. _g_dbus_debug_print_unlock ();
  567. }
  568. /* Every async read that uses this callback uses worker->cancellable
  569. * as its GCancellable. worker->cancellable gets cancelled if and only
  570. * if the GDBusConnection tells us to close (either via
  571. * _g_dbus_worker_stop, which is called on last-unref, or directly),
  572. * so a cancelled read must mean our connection was closed locally.
  573. *
  574. * If we're closing, other errors are possible - notably,
  575. * G_IO_ERROR_CLOSED can be seen if we close the stream with an async
  576. * read in-flight. It seems sensible to treat all read errors during
  577. * closing as an expected thing that doesn't trip exit-on-close.
  578. *
  579. * Because close_expected can't be set until we get into the worker
  580. * thread, but the cancellable is signalled sooner (from another
  581. * thread), we do still need to check the error.
  582. */
  583. if (worker->close_expected ||
  584. g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
  585. _g_dbus_worker_emit_disconnected (worker, FALSE, NULL);
  586. else
  587. _g_dbus_worker_emit_disconnected (worker, TRUE, error);
  588. g_error_free (error);
  589. goto out;
  590. }
  591. #if 0
  592. g_debug ("read %d bytes (is_closed=%d blocking=%d condition=0x%02x) stream %p, %p",
  593. (gint) bytes_read,
  594. g_socket_is_closed (g_socket_connection_get_socket (G_SOCKET_CONNECTION (worker->stream))),
  595. g_socket_get_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (worker->stream))),
  596. g_socket_condition_check (g_socket_connection_get_socket (G_SOCKET_CONNECTION (worker->stream)),
  597. G_IO_IN | G_IO_OUT | G_IO_HUP),
  598. worker->stream,
  599. worker);
  600. #endif
  601. /* TODO: hmm, hmm... */
  602. if (bytes_read == 0)
  603. {
  604. g_set_error (&error,
  605. G_IO_ERROR,
  606. G_IO_ERROR_FAILED,
  607. "Underlying GIOStream returned 0 bytes on an async read");
  608. _g_dbus_worker_emit_disconnected (worker, TRUE, error);
  609. g_error_free (error);
  610. goto out;
  611. }
  612. read_message_print_transport_debug (bytes_read, worker);
  613. worker->read_buffer_cur_size += bytes_read;
  614. if (worker->read_buffer_bytes_wanted == worker->read_buffer_cur_size)
  615. {
  616. /* OK, got what we asked for! */
  617. if (worker->read_buffer_bytes_wanted == 16)
  618. {
  619. gssize message_len;
  620. /* OK, got the header - determine how many more bytes are needed */
  621. error = NULL;
  622. message_len = g_dbus_message_bytes_needed ((guchar *) worker->read_buffer,
  623. 16,
  624. &error);
  625. if (message_len == -1)
  626. {
  627. g_warning ("_g_dbus_worker_do_read_cb: error determining bytes needed: %s", error->message);
  628. _g_dbus_worker_emit_disconnected (worker, FALSE, error);
  629. g_error_free (error);
  630. goto out;
  631. }
  632. worker->read_buffer_bytes_wanted = message_len;
  633. _g_dbus_worker_do_read_unlocked (worker);
  634. }
  635. else
  636. {
  637. GDBusMessage *message;
  638. error = NULL;
  639. /* TODO: use connection->priv->auth to decode the message */
  640. message = g_dbus_message_new_from_blob ((guchar *) worker->read_buffer,
  641. worker->read_buffer_cur_size,
  642. worker->capabilities,
  643. &error);
  644. if (message == NULL)
  645. {
  646. gchar *s;
  647. s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
  648. g_warning ("Error decoding D-Bus message of %" G_GSIZE_FORMAT " bytes\n"
  649. "The error is: %s\n"
  650. "The payload is as follows:\n"
  651. "%s\n",
  652. worker->read_buffer_cur_size,
  653. error->message,
  654. s);
  655. g_free (s);
  656. _g_dbus_worker_emit_disconnected (worker, FALSE, error);
  657. g_error_free (error);
  658. goto out;
  659. }
  660. #ifdef G_OS_UNIX
  661. if (worker->read_fd_list != NULL)
  662. {
  663. g_dbus_message_set_unix_fd_list (message, worker->read_fd_list);
  664. g_object_unref (worker->read_fd_list);
  665. worker->read_fd_list = NULL;
  666. }
  667. #endif
  668. if (G_UNLIKELY (_g_dbus_debug_message ()))
  669. {
  670. gchar *s;
  671. _g_dbus_debug_print_lock ();
  672. g_print ("========================================================================\n"
  673. "GDBus-debug:Message:\n"
  674. " <<<< RECEIVED D-Bus message (%" G_GSIZE_FORMAT " bytes)\n",
  675. worker->read_buffer_cur_size);
  676. s = g_dbus_message_print (message, 2);
  677. g_print ("%s", s);
  678. g_free (s);
  679. if (G_UNLIKELY (_g_dbus_debug_payload ()))
  680. {
  681. s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
  682. g_print ("%s\n", s);
  683. g_free (s);
  684. }
  685. _g_dbus_debug_print_unlock ();
  686. }
  687. /* yay, got a message, go deliver it */
  688. _g_dbus_worker_queue_or_deliver_received_message (worker, message);
  689. /* start reading another message! */
  690. worker->read_buffer_bytes_wanted = 0;
  691. worker->read_buffer_cur_size = 0;
  692. _g_dbus_worker_do_read_unlocked (worker);
  693. }
  694. }
  695. else
  696. {
  697. /* didn't get all the bytes we requested - so repeat the request... */
  698. _g_dbus_worker_do_read_unlocked (worker);
  699. }
  700. out:
  701. g_mutex_unlock (&worker->read_lock);
  702. /* gives up the reference acquired when calling g_input_stream_read_async() */
  703. _g_dbus_worker_unref (worker);
  704. /* check if there is any pending close */
  705. schedule_pending_close (worker);
  706. }
  707. /* called in private thread shared by all GDBusConnection instances (with read-lock held) */
  708. static void
  709. _g_dbus_worker_do_read_unlocked (GDBusWorker *worker)
  710. {
  711. /* Note that we do need to keep trying to read even if close_expected is
  712. * true, because only failing a read causes us to signal 'closed'.
  713. */
  714. /* if bytes_wanted is zero, it means start reading a message */
  715. if (worker->read_buffer_bytes_wanted == 0)
  716. {
  717. worker->read_buffer_cur_size = 0;
  718. worker->read_buffer_bytes_wanted = 16;
  719. }
  720. /* ensure we have a (big enough) buffer */
  721. if (worker->read_buffer == NULL || worker->read_buffer_bytes_wanted > worker->read_buffer_allocated_size)
  722. {
  723. /* TODO: 4096 is randomly chosen; might want a better chosen default minimum */
  724. worker->read_buffer_allocated_size = MAX (worker->read_buffer_bytes_wanted, 4096);
  725. worker->read_buffer = g_realloc (worker->read_buffer, worker->read_buffer_allocated_size);
  726. }
  727. if (worker->socket == NULL)
  728. g_input_stream_read_async (g_io_stream_get_input_stream (worker->stream),
  729. worker->read_buffer + worker->read_buffer_cur_size,
  730. worker->read_buffer_bytes_wanted - worker->read_buffer_cur_size,
  731. G_PRIORITY_DEFAULT,
  732. worker->cancellable,
  733. (GAsyncReadyCallback) _g_dbus_worker_do_read_cb,
  734. _g_dbus_worker_ref (worker));
  735. else
  736. {
  737. worker->read_ancillary_messages = NULL;
  738. worker->read_num_ancillary_messages = 0;
  739. _g_socket_read_with_control_messages (worker->socket,
  740. worker->read_buffer + worker->read_buffer_cur_size,
  741. worker->read_buffer_bytes_wanted - worker->read_buffer_cur_size,
  742. &worker->read_ancillary_messages,
  743. &worker->read_num_ancillary_messages,
  744. G_PRIORITY_DEFAULT,
  745. worker->cancellable,
  746. (GAsyncReadyCallback) _g_dbus_worker_do_read_cb,
  747. _g_dbus_worker_ref (worker));
  748. }
  749. }
  750. /* called in private thread shared by all GDBusConnection instances (without read-lock held) */
  751. static gboolean
  752. _g_dbus_worker_do_initial_read (gpointer data)
  753. {
  754. GDBusWorker *worker = data;
  755. g_mutex_lock (&worker->read_lock);
  756. _g_dbus_worker_do_read_unlocked (worker);
  757. g_mutex_unlock (&worker->read_lock);
  758. return FALSE;
  759. }
  760. /* ---------------------------------------------------------------------------------------------------- */
  761. struct _MessageToWriteData
  762. {
  763. GDBusWorker *worker;
  764. GDBusMessage *message;
  765. gchar *blob;
  766. gsize blob_size;
  767. gsize total_written;
  768. GTask *task;
  769. };
  770. static void
  771. message_to_write_data_free (MessageToWriteData *data)
  772. {
  773. _g_dbus_worker_unref (data->worker);
  774. if (data->message)
  775. g_object_unref (data->message);
  776. g_free (data->blob);
  777. g_slice_free (MessageToWriteData, data);
  778. }
  779. /* ---------------------------------------------------------------------------------------------------- */
  780. static void write_message_continue_writing (MessageToWriteData *data);
  781. /* called in private thread shared by all GDBusConnection instances
  782. *
  783. * write-lock is not held on entry
  784. * output_pending is PENDING_WRITE on entry
  785. */
  786. static void
  787. write_message_async_cb (GObject *source_object,
  788. GAsyncResult *res,
  789. gpointer user_data)
  790. {
  791. MessageToWriteData *data = user_data;
  792. GTask *task;
  793. gssize bytes_written;
  794. GError *error;
  795. /* Note: we can't access data->task after calling g_task_return_* () because the
  796. * callback can free @data and we're not completing in idle. So use a copy of the pointer.
  797. */
  798. task = data->task;
  799. error = NULL;
  800. bytes_written = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object),
  801. res,
  802. &error);
  803. if (bytes_written == -1)
  804. {
  805. g_task_return_error (task, error);
  806. g_object_unref (task);
  807. goto out;
  808. }
  809. g_assert (bytes_written > 0); /* zero is never returned */
  810. write_message_print_transport_debug (bytes_written, data);
  811. data->total_written += bytes_written;
  812. g_assert (data->total_written <= data->blob_size);
  813. if (data->total_written == data->blob_size)
  814. {
  815. g_task_return_boolean (task, TRUE);
  816. g_object_unref (task);
  817. goto out;
  818. }
  819. write_message_continue_writing (data);
  820. out:
  821. ;
  822. }
  823. /* called in private thread shared by all GDBusConnection instances
  824. *
  825. * write-lock is not held on entry
  826. * output_pending is PENDING_WRITE on entry
  827. */
  828. #ifdef G_OS_UNIX
  829. static gboolean
  830. on_socket_ready (GSocket *socket,
  831. GIOCondition condition,
  832. gpointer user_data)
  833. {
  834. MessageToWriteData *data = user_data;
  835. write_message_continue_writing (data);
  836. return FALSE; /* remove source */
  837. }
  838. #endif
  839. /* called in private thread shared by all GDBusConnection instances
  840. *
  841. * write-lock is not held on entry
  842. * output_pending is PENDING_WRITE on entry
  843. */
  844. static void
  845. write_message_continue_writing (MessageToWriteData *data)
  846. {
  847. GOutputStream *ostream;
  848. #ifdef G_OS_UNIX
  849. GTask *task;
  850. GUnixFDList *fd_list;
  851. #endif
  852. #ifdef G_OS_UNIX
  853. /* Note: we can't access data->task after calling g_task_return_* () because the
  854. * callback can free @data and we're not completing in idle. So use a copy of the pointer.
  855. */
  856. task = data->task;
  857. #endif
  858. ostream = g_io_stream_get_output_stream (data->worker->stream);
  859. #ifdef G_OS_UNIX
  860. fd_list = g_dbus_message_get_unix_fd_list (data->message);
  861. #endif
  862. g_assert (!g_output_stream_has_pending (ostream));
  863. g_assert_cmpint (data->total_written, <, data->blob_size);
  864. if (FALSE)
  865. {
  866. }
  867. #ifdef G_OS_UNIX
  868. else if (G_IS_SOCKET_OUTPUT_STREAM (ostream) && data->total_written == 0)
  869. {
  870. GOutputVector vector;
  871. GSocketControlMessage *control_message;
  872. gssize bytes_written;
  873. GError *error;
  874. vector.buffer = data->blob;
  875. vector.size = data->blob_size;
  876. control_message = NULL;
  877. if (fd_list != NULL && g_unix_fd_list_get_length (fd_list) > 0)
  878. {
  879. if (!(data->worker->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING))
  880. {
  881. g_task_return_new_error (task,
  882. G_IO_ERROR,
  883. G_IO_ERROR_FAILED,
  884. "Tried sending a file descriptor but remote peer does not support this capability");
  885. g_object_unref (task);
  886. goto out;
  887. }
  888. control_message = g_unix_fd_message_new_with_fd_list (fd_list);
  889. }
  890. error = NULL;
  891. bytes_written = g_socket_send_message (data->worker->socket,
  892. NULL, /* address */
  893. &vector,
  894. 1,
  895. control_message != NULL ? &control_message : NULL,
  896. control_message != NULL ? 1 : 0,
  897. G_SOCKET_MSG_NONE,
  898. data->worker->cancellable,
  899. &error);
  900. if (control_message != NULL)
  901. g_object_unref (control_message);
  902. if (bytes_written == -1)
  903. {
  904. /* Handle WOULD_BLOCK by waiting until there's room in the buffer */
  905. if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
  906. {
  907. GSource *source;
  908. source = g_socket_create_source (data->worker->socket,
  909. G_IO_OUT | G_IO_HUP | G_IO_ERR,
  910. data->worker->cancellable);
  911. g_source_set_callback (source,
  912. (GSourceFunc) on_socket_ready,
  913. data,
  914. NULL); /* GDestroyNotify */
  915. g_source_attach (source, g_main_context_get_thread_default ());
  916. g_source_unref (source);
  917. g_error_free (error);
  918. goto out;
  919. }
  920. g_task_return_error (task, error);
  921. g_object_unref (task);
  922. goto out;
  923. }
  924. g_assert (bytes_written > 0); /* zero is never returned */
  925. write_message_print_transport_debug (bytes_written, data);
  926. data->total_written += bytes_written;
  927. g_assert (data->total_written <= data->blob_size);
  928. if (data->total_written == data->blob_size)
  929. {
  930. g_task_return_boolean (task, TRUE);
  931. g_object_unref (task);
  932. goto out;
  933. }
  934. write_message_continue_writing (data);
  935. }
  936. #endif
  937. else
  938. {
  939. #ifdef G_OS_UNIX
  940. if (fd_list != NULL)
  941. {
  942. g_task_return_new_error (task,
  943. G_IO_ERROR,
  944. G_IO_ERROR_FAILED,
  945. "Tried sending a file descriptor on unsupported stream of type %s",
  946. g_type_name (G_TYPE_FROM_INSTANCE (ostream)));
  947. g_object_unref (task);
  948. goto out;
  949. }
  950. #endif
  951. g_output_stream_write_async (ostream,
  952. (const gchar *) data->blob + data->total_written,
  953. data->blob_size - data->total_written,
  954. G_PRIORITY_DEFAULT,
  955. data->worker->cancellable,
  956. write_message_async_cb,
  957. data);
  958. }
  959. #ifdef G_OS_UNIX
  960. out:
  961. #endif
  962. ;
  963. }
  964. /* called in private thread shared by all GDBusConnection instances
  965. *
  966. * write-lock is not held on entry
  967. * output_pending is PENDING_WRITE on entry
  968. */
  969. static void
  970. write_message_async (GDBusWorker *worker,
  971. MessageToWriteData *data,
  972. GAsyncReadyCallback callback,
  973. gpointer user_data)
  974. {
  975. data->task = g_task_new (NULL, NULL, callback, user_data);
  976. g_task_set_source_tag (data->task, write_message_async);
  977. data->total_written = 0;
  978. write_message_continue_writing (data);
  979. }
  980. /* called in private thread shared by all GDBusConnection instances (with write-lock held) */
  981. static gboolean
  982. write_message_finish (GAsyncResult *res,
  983. GError **error)
  984. {
  985. g_return_val_if_fail (g_task_is_valid (res, NULL), FALSE);
  986. return g_task_propagate_boolean (G_TASK (res), error);
  987. }
  988. /* ---------------------------------------------------------------------------------------------------- */
  989. static void continue_writing (GDBusWorker *worker);
  990. typedef struct
  991. {
  992. GDBusWorker *worker;
  993. GList *flushers;
  994. } FlushAsyncData;
  995. static void
  996. flush_data_list_complete (const GList *flushers,
  997. const GError *error)
  998. {
  999. const GList *l;
  1000. for (l = flushers; l != NULL; l = l->next)
  1001. {
  1002. FlushData *f = l->data;
  1003. f->error = error != NULL ? g_error_copy (error) : NULL;
  1004. g_mutex_lock (&f->mutex);
  1005. g_cond_signal (&f->cond);
  1006. g_mutex_unlock (&f->mutex);
  1007. }
  1008. }
  1009. /* called in private thread shared by all GDBusConnection instances
  1010. *
  1011. * write-lock is not held on entry
  1012. * output_pending is PENDING_FLUSH on entry
  1013. */
  1014. static void
  1015. ostream_flush_cb (GObject *source_object,
  1016. GAsyncResult *res,
  1017. gpointer user_data)
  1018. {
  1019. FlushAsyncData *data = user_data;
  1020. GError *error;
  1021. error = NULL;
  1022. g_output_stream_flush_finish (G_OUTPUT_STREAM (source_object),
  1023. res,
  1024. &error);
  1025. if (error == NULL)
  1026. {
  1027. if (G_UNLIKELY (_g_dbus_debug_transport ()))
  1028. {
  1029. _g_dbus_debug_print_lock ();
  1030. g_print ("========================================================================\n"
  1031. "GDBus-debug:Transport:\n"
  1032. " ---- FLUSHED stream of type %s\n",
  1033. g_type_name (G_TYPE_FROM_INSTANCE (g_io_stream_get_output_stream (data->worker->stream))));
  1034. _g_dbus_debug_print_unlock ();
  1035. }
  1036. }
  1037. g_assert (data->flushers != NULL);
  1038. flush_data_list_complete (data->flushers, error);
  1039. g_list_free (data->flushers);
  1040. if (error != NULL)
  1041. g_error_free (error);
  1042. /* Make sure we tell folks that we don't have additional
  1043. flushes pending */
  1044. g_mutex_lock (&data->worker->write_lock);
  1045. data->worker->write_num_messages_flushed = data->worker->write_num_messages_written;
  1046. g_assert (data->worker->output_pending == PENDING_FLUSH);
  1047. data->worker->output_pending = PENDING_NONE;
  1048. g_mutex_unlock (&data->worker->write_lock);
  1049. /* OK, cool, finally kick off the next write */
  1050. continue_writing (data->worker);
  1051. _g_dbus_worker_unref (data->worker);
  1052. g_free (data);
  1053. }
  1054. /* called in private thread shared by all GDBusConnection instances
  1055. *
  1056. * write-lock is not held on entry
  1057. * output_pending is PENDING_FLUSH on entry
  1058. */
  1059. static void
  1060. start_flush (FlushAsyncData *data)
  1061. {
  1062. g_output_stream_flush_async (g_io_stream_get_output_stream (data->worker->stream),
  1063. G_PRIORITY_DEFAULT,
  1064. data->worker->cancellable,
  1065. ostream_flush_cb,
  1066. data);
  1067. }
  1068. /* called in private thread shared by all GDBusConnection instances
  1069. *
  1070. * write-lock is held on entry
  1071. * output_pending is PENDING_NONE on entry
  1072. */
  1073. static void
  1074. message_written_unlocked (GDBusWorker *worker,
  1075. MessageToWriteData *message_data)
  1076. {
  1077. if (G_UNLIKELY (_g_dbus_debug_message ()))
  1078. {
  1079. gchar *s;
  1080. _g_dbus_debug_print_lock ();
  1081. g_print ("========================================================================\n"
  1082. "GDBus-debug:Message:\n"
  1083. " >>>> SENT D-Bus message (%" G_GSIZE_FORMAT " bytes)\n",
  1084. message_data->blob_size);
  1085. s = g_dbus_message_print (message_data->message, 2);
  1086. g_print ("%s", s);
  1087. g_free (s);
  1088. if (G_UNLIKELY (_g_dbus_debug_payload ()))
  1089. {
  1090. s = _g_dbus_hexdump (message_data->blob, message_data->blob_size, 2);
  1091. g_print ("%s\n", s);
  1092. g_free (s);
  1093. }
  1094. _g_dbus_debug_print_unlock ();
  1095. }
  1096. worker->write_num_messages_written += 1;
  1097. }
  1098. /* called in private thread shared by all GDBusConnection instances
  1099. *
  1100. * write-lock is held on entry
  1101. * output_pending is PENDING_NONE on entry
  1102. *
  1103. * Returns: non-%NULL, setting @output_pending, if we need to flush now
  1104. */
  1105. static FlushAsyncData *
  1106. prepare_flush_unlocked (GDBusWorker *worker)
  1107. {
  1108. GList *l;
  1109. GList *ll;
  1110. GList *flushers;
  1111. flushers = NULL;
  1112. for (l = worker->write_pending_flushes; l != NULL; l = ll)
  1113. {
  1114. FlushData *f = l->data;
  1115. ll = l->next;
  1116. if (f->number_to_wait_for == worker->write_num_messages_written)
  1117. {
  1118. flushers = g_list_append (flushers, f);
  1119. worker->write_pending_flushes = g_list_delete_link (worker->write_pending_flushes, l);
  1120. }
  1121. }
  1122. if (flushers != NULL)
  1123. {
  1124. g_assert (worker->output_pending == PENDING_NONE);
  1125. worker->output_pending = PENDING_FLUSH;
  1126. }
  1127. if (flushers != NULL)
  1128. {
  1129. FlushAsyncData *data;
  1130. data = g_new0 (FlushAsyncData, 1);
  1131. data->worker = _g_dbus_worker_ref (worker);
  1132. data->flushers = flushers;
  1133. return data;
  1134. }
  1135. return NULL;
  1136. }
  1137. /* called in private thread shared by all GDBusConnection instances
  1138. *
  1139. * write-lock is not held on entry
  1140. * output_pending is PENDING_WRITE on entry
  1141. */
  1142. static void
  1143. write_message_cb (GObject *source_object,
  1144. GAsyncResult *res,
  1145. gpointer user_data)
  1146. {
  1147. MessageToWriteData *data = user_data;
  1148. GError *error;
  1149. g_mutex_lock (&data->worker->write_lock);
  1150. g_assert (data->worker->output_pending == PENDING_WRITE);
  1151. data->worker->output_pending = PENDING_NONE;
  1152. error = NULL;
  1153. if (!write_message_finish (res, &error))
  1154. {
  1155. g_mutex_unlock (&data->worker->write_lock);
  1156. /* TODO: handle */
  1157. _g_dbus_worker_emit_disconnected (data->worker, TRUE, error);
  1158. g_error_free (error);
  1159. g_mutex_lock (&data->worker->write_lock);
  1160. }
  1161. message_written_unlocked (data->worker, data);
  1162. g_mutex_unlock (&data->worker->write_lock);
  1163. continue_writing (data->worker);
  1164. message_to_write_data_free (data);
  1165. }
  1166. /* called in private thread shared by all GDBusConnection instances
  1167. *
  1168. * write-lock is not held on entry
  1169. * output_pending is PENDING_CLOSE on entry
  1170. */
  1171. static void
  1172. iostream_close_cb (GObject *source_object,
  1173. GAsyncResult *res,
  1174. gpointer user_data)
  1175. {
  1176. GDBusWorker *worker = user_data;
  1177. GError *error = NULL;
  1178. GList *pending_close_attempts, *pending_flush_attempts;
  1179. GQueue *send_queue;
  1180. g_io_stream_close_finish (worker->stream, res, &error);
  1181. g_mutex_lock (&worker->write_lock);
  1182. pending_close_attempts = worker->pending_close_attempts;
  1183. worker->pending_close_attempts = NULL;
  1184. pending_flush_attempts = worker->write_pending_flushes;
  1185. worker->write_pending_flushes = NULL;
  1186. send_queue = worker->write_queue;
  1187. worker->write_queue = g_queue_new ();
  1188. g_assert (worker->output_pending == PENDING_CLOSE);
  1189. worker->output_pending = PENDING_NONE;
  1190. g_mutex_unlock (&worker->write_lock);
  1191. while (pending_close_attempts != NULL)
  1192. {
  1193. CloseData *close_data = pending_close_attempts->data;
  1194. pending_close_attempts = g_list_delete_link (pending_close_attempts,
  1195. pending_close_attempts);
  1196. if (close_data->task != NULL)
  1197. {
  1198. if (error != NULL)
  1199. g_task_return_error (close_data->task, g_error_copy (error));
  1200. else
  1201. g_task_return_boolean (close_data->task, TRUE);
  1202. }
  1203. close_data_free (close_data);
  1204. }
  1205. g_clear_error (&error);
  1206. /* all messages queued for sending are discarded */
  1207. g_queue_free_full (send_queue, (GDestroyNotify) message_to_write_data_free);
  1208. /* all queued flushes fail */
  1209. error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED,
  1210. _("Operation was cancelled"));
  1211. flush_data_list_complete (pending_flush_attempts, error);
  1212. g_list_free (pending_flush_attempts);
  1213. g_clear_error (&error);
  1214. _g_dbus_worker_unref (worker);
  1215. }
  1216. /* called in private thread shared by all GDBusConnection instances
  1217. *
  1218. * write-lock is not held on entry
  1219. * output_pending must be PENDING_NONE on entry
  1220. */
  1221. static void
  1222. continue_writing (GDBusWorker *worker)
  1223. {
  1224. MessageToWriteData *data;
  1225. FlushAsyncData *flush_async_data;
  1226. write_next:
  1227. /* we mustn't try to write two things at once */
  1228. g_assert (worker->output_pending == PENDING_NONE);
  1229. g_mutex_lock (&worker->write_lock);
  1230. data = NULL;
  1231. flush_async_data = NULL;
  1232. /* if we want to close the connection, that takes precedence */
  1233. if (worker->pending_close_attempts != NULL)
  1234. {
  1235. GInputStream *input = g_io_stream_get_input_stream (worker->stream);
  1236. if (!g_input_stream_has_pending (input))
  1237. {
  1238. worker->close_expected = TRUE;
  1239. worker->output_pending = PENDING_CLOSE;
  1240. g_io_stream_close_async (worker->stream, G_PRIORITY_DEFAULT,
  1241. NULL, iostream_close_cb,
  1242. _g_dbus_worker_ref (worker));
  1243. }
  1244. }
  1245. else
  1246. {
  1247. flush_async_data = prepare_flush_unlocked (worker);
  1248. if (flush_async_data == NULL)
  1249. {
  1250. data = g_queue_pop_head (worker->write_queue);
  1251. if (data != NULL)
  1252. worker->output_pending = PENDING_WRITE;
  1253. }
  1254. }
  1255. g_mutex_unlock (&worker->write_lock);
  1256. /* Note that write_lock is only used for protecting the @write_queue
  1257. * and @output_pending fields of the GDBusWorker struct ... which we
  1258. * need to modify from arbitrary threads in _g_dbus_worker_send_message().
  1259. *
  1260. * Therefore, it's fine to drop it here when calling back into user
  1261. * code and then writing the message out onto the GIOStream since this
  1262. * function only runs on the worker thread.
  1263. */
  1264. if (flush_async_data != NULL)
  1265. {
  1266. start_flush (flush_async_data);
  1267. g_assert (data == NULL);
  1268. }
  1269. else if (data != NULL)
  1270. {
  1271. GDBusMessage *old_message;
  1272. guchar *new_blob;
  1273. gsize new_blob_size;
  1274. GError *error;
  1275. old_message = data->message;
  1276. data->message = _g_dbus_worker_emit_message_about_to_be_sent (worker, data->message);
  1277. if (data->message == old_message)
  1278. {
  1279. /* filters had no effect - do nothing */
  1280. }
  1281. else if (data->message == NULL)
  1282. {
  1283. /* filters dropped message */
  1284. g_mutex_lock (&worker->write_lock);
  1285. worker->output_pending = PENDING_NONE;
  1286. g_mutex_unlock (&worker->write_lock);
  1287. message_to_write_data_free (data);
  1288. goto write_next;
  1289. }
  1290. else
  1291. {
  1292. /* filters altered the message -> reencode */
  1293. error = NULL;
  1294. new_blob = g_dbus_message_to_blob (data->message,
  1295. &new_blob_size,
  1296. worker->capabilities,
  1297. &error);
  1298. if (new_blob == NULL)
  1299. {
  1300. /* if filter make the GDBusMessage unencodeable, just complain on stderr and send
  1301. * the old message instead
  1302. */
  1303. g_warning ("Error encoding GDBusMessage with serial %d altered by filter function: %s",
  1304. g_dbus_message_get_serial (data->message),
  1305. error->message);
  1306. g_error_free (error);
  1307. }
  1308. else
  1309. {
  1310. g_free (data->blob);
  1311. data->blob = (gchar *) new_blob;

Large files files are truncated, but you can click here to view the full file