Пример #1
0
/**
 * g_pollable_source_new_full:
 * @pollable_stream: (type GObject): the stream associated with the
 *   new source
 * @child_source: (allow-none): optional child source to attach
 * @cancellable: (allow-none): optional #GCancellable to attach
 *
 * Utility method for #GPollableInputStream and #GPollableOutputStream
 * implementations. Creates a new #GSource, as with
 * g_pollable_source_new(), but also attaching @child_source (with a
 * dummy callback), and @cancellable, if they are non-%NULL.
 *
 * Return value: (transfer full): the new #GSource.
 *
 * Since: 2.34
 */
GSource *
g_pollable_source_new_full (gpointer      pollable_stream,
			    GSource      *child_source,
			    GCancellable *cancellable)
{
  GSource *source;

  g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) ||
			G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL);

  source = g_pollable_source_new (pollable_stream);
  if (child_source)
    {
      g_source_set_dummy_callback (child_source);
      g_source_add_child_source (source, child_source);
    }
  if (cancellable)
    {
      GSource *cancellable_source = g_cancellable_source_new (cancellable);

      g_source_set_dummy_callback (cancellable_source);
      g_source_add_child_source (source, cancellable_source);
      g_source_unref (cancellable_source);
    }

  return source;
}
Пример #2
0
static GSource *
nice_output_stream_create_source (GPollableOutputStream *stream,
    GCancellable *cancellable)
{
  NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
  GSource *component_source = NULL;
  NiceComponent *component = NULL;
  NiceStream *_stream = NULL;
  NiceAgent *agent;  /* owned */

  component_source = g_pollable_source_new (G_OBJECT (stream));

  if (cancellable) {
    GSource *cancellable_source = g_cancellable_source_new (cancellable);

    g_source_set_dummy_callback (cancellable_source);
    g_source_add_child_source (component_source, cancellable_source);
    g_source_unref (cancellable_source);
  }

  /* Closed streams cannot have sources. */
  if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
    return component_source;

  /* Has the agent disappeared? */
  agent = g_weak_ref_get (&priv->agent_ref);
  if (agent == NULL)
    return component_source;

  agent_lock ();

  /* Grab the socket for this component. */
  if (!agent_find_component (agent, priv->stream_id, priv->component_id,
          &_stream, &component)) {
    g_warning ("Could not find component %u in stream %u", priv->component_id,
        priv->stream_id);
    goto done;
  }

   if (component->tcp_writable_cancellable) {
    GSource *cancellable_source =
        g_cancellable_source_new (component->tcp_writable_cancellable);

    g_source_set_dummy_callback (cancellable_source);
    g_source_add_child_source (component_source, cancellable_source);
    g_source_unref (cancellable_source);
  }

done:
  agent_unlock ();

  g_object_unref (agent);

  return component_source;
}
Пример #3
0
GSource *
g_tls_connection_base_create_source (GTlsConnectionBase  *tls,
				     GIOCondition         condition,
				     GCancellable        *cancellable)
{
  GSource *source, *cancellable_source;
  GTlsConnectionBaseSource *tls_source;

  source = g_source_new (&tls_source_funcs, sizeof (GTlsConnectionBaseSource));
  g_source_set_name (source, "GTlsConnectionBaseSource");
  tls_source = (GTlsConnectionBaseSource *)source;
  tls_source->tls = g_object_ref (tls);
  tls_source->condition = condition;
  if (condition & G_IO_IN)
    tls_source->stream = G_OBJECT (tls->tls_istream);
  else if (condition & G_IO_OUT)
    tls_source->stream = G_OBJECT (tls->tls_ostream);

  tls_source->op_waiting = (gboolean) -1;
  tls_source->io_waiting = (gboolean) -1;
  tls_source_sync (tls_source);

  if (cancellable)
    {
      cancellable_source = g_cancellable_source_new (cancellable);
      g_source_set_dummy_callback (cancellable_source);
      g_source_add_child_source (source, cancellable_source);
      g_source_unref (cancellable_source);
    }

  return source;
}
Пример #4
0
GSource *
_g_fd_source_new (int           fd,
		  gushort       events,
		  GCancellable *cancellable)
{
  GSource *source;
  FDSource *fd_source;

  source = g_source_new (&fd_source_funcs, sizeof (FDSource));
  fd_source = (FDSource *)source;

  fd_source->pollfd.fd = fd;
  fd_source->pollfd.events = events;
  g_source_add_poll (source, &fd_source->pollfd);

  if (cancellable)
    {
      GSource *cancellable_source = g_cancellable_source_new (cancellable);

      g_source_set_dummy_callback (cancellable_source);
      g_source_add_child_source (source, cancellable_source);
      g_source_unref (cancellable_source);
    }

  return source;
}
/**
 * message_queue_source_new:
 * @queue: the queue to check
 * @destroy_message: (nullable): function to free a message, or %NULL
 * @cancellable: (nullable): a #GCancellable, or %NULL
 *
 * Create a new #MessageQueueSource, a type of #GSource which dispatches for
 * each message queued to it.
 *
 * If a callback function of type #MessageQueueSourceFunc is connected to the
 * returned #GSource using g_source_set_callback(), it will be invoked for each
 * message, with the message passed as its first argument. It is responsible for
 * freeing the message. If no callback is set, messages are automatically freed
 * as they are queued.
 *
 * Returns: (transfer full): a new #MessageQueueSource
 */
GSource *
message_queue_source_new (GAsyncQueue    *queue,
                          GDestroyNotify  destroy_message,
                          GCancellable   *cancellable)
{
  GSource *source;  /* alias of @message_queue_source */
  MessageQueueSource *message_queue_source;  /* alias of @source */

  g_return_val_if_fail (queue != NULL, NULL);
  g_return_val_if_fail (cancellable == NULL ||
                        G_IS_CANCELLABLE (cancellable), NULL);

  source = g_source_new (&message_queue_source_funcs,
                         sizeof (MessageQueueSource));
  message_queue_source = (MessageQueueSource *) source;

  /* The caller can overwrite this name with something more useful later. */
  g_source_set_name (source, "MessageQueueSource");

  message_queue_source->queue = g_async_queue_ref (queue);
  message_queue_source->destroy_message = destroy_message;

  /* Add a cancellable source. */
  if (cancellable != NULL)
    {
      GSource *cancellable_source;

      cancellable_source = g_cancellable_source_new (cancellable);
      g_source_set_dummy_callback (cancellable_source);
      g_source_add_child_source (source, cancellable_source);
      g_source_unref (cancellable_source);
    }

  return source;
}
Пример #6
0
/**
 * nice_component_source_new:
 * @agent: a #NiceAgent
 * @stream_id: The stream's id
 * @component_id: The component's number
 * @pollable_stream: a #GPollableInputStream or #GPollableOutputStream to pass
 * to dispatched callbacks
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 *
 * Create a new #ComponentSource, a type of #GSource which proxies poll events
 * from all sockets in the given @component.
 *
 * A callback function of type #GPollableSourceFunc must be connected to the
 * returned #GSource using g_source_set_callback(). @pollable_stream is passed
 * to all callbacks dispatched from the #GSource, and a reference is held on it
 * by the #GSource.
 *
 * The #GSource will automatically update to poll sockets as they’re added to
 * the @component (e.g. during peer discovery).
 *
 * Returns: (transfer full): a new #ComponentSource; unref with g_source_unref()
 */
GSource *
nice_component_input_source_new (NiceAgent *agent, guint stream_id,
    guint component_id, GPollableInputStream *pollable_istream,
    GCancellable *cancellable)
{
  ComponentSource *component_source;

  g_assert (G_IS_POLLABLE_INPUT_STREAM (pollable_istream));

  component_source =
      (ComponentSource *)
          g_source_new (&component_source_funcs, sizeof (ComponentSource));
  g_source_set_name ((GSource *) component_source, "ComponentSource");

  component_source->component_socket_sources_age = 0;
  component_source->pollable_stream = g_object_ref (pollable_istream);
  g_weak_ref_init (&component_source->agent_ref, agent);
  component_source->stream_id = stream_id;
  component_source->component_id = component_id;

  /* Add a cancellable source. */
  if (cancellable != NULL) {
    GSource *cancellable_source;

    cancellable_source = g_cancellable_source_new (cancellable);
    g_source_set_dummy_callback (cancellable_source);
    g_source_add_child_source ((GSource *) component_source,
        cancellable_source);
    g_source_unref (cancellable_source);
  }

  return (GSource *) component_source;
}
Пример #7
0
static void
tls_source_sync (GTlsConnectionBaseSource *tls_source)
{
  GTlsConnectionBase *tls = tls_source->tls;
  gboolean io_waiting, op_waiting;

  /* Was the source destroyed earlier in this main context iteration? */
  if (g_source_is_destroyed ((GSource *) tls_source))
    return;

  g_mutex_lock (&tls->op_mutex);
  if (((tls_source->condition & G_IO_IN) && tls->reading) ||
      ((tls_source->condition & G_IO_OUT) && tls->writing) ||
      (tls->handshaking && !tls->need_finish_handshake))
    op_waiting = TRUE;
  else
    op_waiting = FALSE;

  if (!op_waiting && !tls->need_handshake &&
      !tls->need_finish_handshake)
    io_waiting = TRUE;
  else
    io_waiting = FALSE;
  g_mutex_unlock (&tls->op_mutex);

  if (op_waiting == tls_source->op_waiting &&
      io_waiting == tls_source->io_waiting)
    return;
  tls_source->op_waiting = op_waiting;
  tls_source->io_waiting = io_waiting;

  if (tls_source->child_source)
    {
      g_source_remove_child_source ((GSource *)tls_source,
				    tls_source->child_source);
      g_source_unref (tls_source->child_source);
    }

  if (op_waiting)
    tls_source->child_source = g_cancellable_source_new (tls->waiting_for_op);
  else if (io_waiting && G_IS_POLLABLE_INPUT_STREAM (tls_source->stream))
    tls_source->child_source = g_pollable_input_stream_create_source (tls->base_istream, NULL);
  else if (io_waiting && G_IS_POLLABLE_OUTPUT_STREAM (tls_source->stream))
    tls_source->child_source = g_pollable_output_stream_create_source (tls->base_ostream, NULL);
  else
    tls_source->child_source = g_timeout_source_new (0);

  g_source_set_dummy_callback (tls_source->child_source);
  g_source_add_child_source ((GSource *)tls_source, tls_source->child_source);
}
Пример #8
0
GSource *
soup_message_io_get_source (SoupMessage *msg, GCancellable *cancellable,
			    SoupMessageSourceFunc callback, gpointer user_data)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	SoupMessageIOData *io = priv->io_data;
	GSource *base_source, *source;
	SoupMessageSource *message_source;

	if (!io) {
		base_source = g_timeout_source_new (0);
	} else if (io->paused) {
		base_source = NULL;
	} else if (io->async_close_wait) {
		base_source = g_cancellable_source_new (io->async_close_wait);
	} else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->read_state)) {
		GPollableInputStream *istream;

		if (io->body_istream)
			istream = G_POLLABLE_INPUT_STREAM (io->body_istream);
		else
			istream = G_POLLABLE_INPUT_STREAM (io->istream);
		base_source = g_pollable_input_stream_create_source (istream, cancellable);
	} else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->write_state)) {
		GPollableOutputStream *ostream;

		if (io->body_ostream)
			ostream = G_POLLABLE_OUTPUT_STREAM (io->body_ostream);
		else
			ostream = G_POLLABLE_OUTPUT_STREAM (io->ostream);
		base_source = g_pollable_output_stream_create_source (ostream, cancellable);
	} else
		base_source = g_timeout_source_new (0);

	source = g_source_new (&message_source_funcs,
			       sizeof (SoupMessageSource));
	g_source_set_name (source, "SoupMessageSource");
	message_source = (SoupMessageSource *)source;
	message_source->msg = g_object_ref (msg);
	message_source->paused = io && io->paused;

	if (base_source) {
		g_source_set_dummy_callback (base_source);
		g_source_add_child_source (source, base_source);
		g_source_unref (base_source);
	}
	g_source_set_callback (source, (GSourceFunc) callback, user_data, NULL);
	return source;
}
Пример #9
0
static GSource *
g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
					    GCancellable         *cancellable)
{
  GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
  GSource *inner_source, *cancellable_source, *pollable_source;

  pollable_source = g_pollable_source_new (G_OBJECT (stream));

  inner_source = g_unix_fd_source_new (unix_stream->priv->fd, G_IO_IN);
  g_source_set_dummy_callback (inner_source);
  g_source_add_child_source (pollable_source, inner_source);
  g_source_unref (inner_source);

  if (cancellable)
    {
      cancellable_source = g_cancellable_source_new (cancellable);
      g_source_set_dummy_callback (cancellable_source);
      g_source_add_child_source (pollable_source, cancellable_source);
      g_source_unref (cancellable_source);
    }

  return pollable_source;
}
static GSource *
g_socket_output_stream_pollable_create_source (GPollableOutputStream *pollable,
        GCancellable          *cancellable)
{
    GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
    GSource *socket_source, *pollable_source;

    pollable_source = g_pollable_source_new (G_OBJECT (output_stream));
    socket_source = g_socket_create_source (output_stream->priv->socket,
                                            G_IO_OUT, cancellable);
    g_source_set_dummy_callback (socket_source);
    g_source_add_child_source (pollable_source, socket_source);
    g_source_unref (socket_source);

    return pollable_source;
}
static GSource *
soup_content_sniffer_stream_create_source (GPollableInputStream *stream,
					   GCancellable         *cancellable)
{
	SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream);
	GSource *base_source, *pollable_source;

	if (sniffer->priv->error ||
	    (!sniffer->priv->sniffing && sniffer->priv->buffer))
		base_source = g_timeout_source_new (0);
	else
		base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (stream)->base_stream), cancellable);

	g_source_set_dummy_callback (base_source);
	pollable_source = g_pollable_source_new (G_OBJECT (stream));
	g_source_add_child_source (pollable_source, base_source);
	g_source_unref (base_source);

	return pollable_source;
}
Пример #12
0
static gboolean io_watch_poll_prepare(GSource *source,
                                      gint *timeout)
{
    IOWatchPoll *iwp = io_watch_poll_from_source(source);
    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
    bool was_active = iwp->src != NULL;
    if (was_active == now_active) {
        return FALSE;
    }

    if (now_active) {
        iwp->src = qio_channel_create_watch(
            iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
        g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
        g_source_add_child_source(source, iwp->src);
        g_source_unref(iwp->src);
    } else {
        g_source_remove_child_source(source, iwp->src);
        iwp->src = NULL;
    }
    return FALSE;
}
Пример #13
0
static GSource *
nice_input_stream_create_source (GPollableInputStream *stream,
    GCancellable *cancellable)
{
  NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
  GSource *component_source = NULL;
  NiceAgent *agent;  /* owned */

  /* Closed streams cannot have sources. */
  if (g_input_stream_is_closed (G_INPUT_STREAM (stream)))
    goto dummy_source;

  /* Has the agent disappeared? */
  agent = g_weak_ref_get (&priv->agent_ref);
  if (agent == NULL)
    goto dummy_source;

  component_source = component_input_source_new (agent, priv->stream_id,
      priv->component_id, stream, cancellable);

  g_object_unref (agent);

  return component_source;

 dummy_source:

  component_source = g_pollable_source_new (G_OBJECT (stream));

  if (cancellable) {
    GSource *cancellable_source = g_cancellable_source_new (cancellable);

    g_source_set_dummy_callback (cancellable_source);
    g_source_add_child_source (component_source, cancellable_source);
    g_source_unref (cancellable_source);
  }

  return component_source;
}
Пример #14
0
static gboolean
component_source_prepare (GSource *source, gint *timeout_)
{
  ComponentSource *component_source = (ComponentSource *) source;
  NiceAgent *agent;
  NiceComponent *component;
  GSList *parentl, *childl;

  agent = g_weak_ref_get (&component_source->agent_ref);
  if (!agent)
    return FALSE;

  /* Needed due to accessing the Component. */
  agent_lock ();

  if (!agent_find_component (agent,
          component_source->stream_id, component_source->component_id, NULL,
          &component))
    goto done;


  if (component->socket_sources_age ==
      component_source->component_socket_sources_age)
    goto done;

  /* If the age has changed, either
   *  - one or more new socket has been prepended
   *  - old sockets have been removed
   */

  /* Add the new child sources. */

  for (parentl = component->socket_sources; parentl; parentl = parentl->next) {
    SocketSource *parent_socket_source = parentl->data;
    SocketSource *child_socket_source;

    if (parent_socket_source->socket->fileno == NULL)
      continue;

    /* Iterating the list of socket sources every time isn't a big problem
     * because the number of pairs is limited ~100 normally, so there will
     * rarely be more than 10.
     */
    childl = g_slist_find_custom (component_source->socket_sources,
        parent_socket_source->socket, _find_socket_source);

    /* If we have reached this state, then all sources new sources have been
     * added, because they are always prepended.
     */
    if (childl)
      break;

    child_socket_source = g_slice_new0 (SocketSource);
    child_socket_source->socket = parent_socket_source->socket;
    child_socket_source->source =
        g_socket_create_source (child_socket_source->socket->fileno, G_IO_IN,
            NULL);
    g_source_set_dummy_callback (child_socket_source->source);
    g_source_add_child_source (source, child_socket_source->source);
    g_source_unref (child_socket_source->source);
    component_source->socket_sources =
        g_slist_prepend (component_source->socket_sources, child_socket_source);
  }


  for (childl = component_source->socket_sources;
       childl;) {
    SocketSource *child_socket_source = childl->data;
    GSList *next = childl->next;

    parentl = g_slist_find_custom (component->socket_sources,
      child_socket_source->socket, _find_socket_source);

    /* If this is not a currently used socket, remove the relevant source */
    if (!parentl) {
      g_source_remove_child_source (source, child_socket_source->source);
      g_slice_free (SocketSource, child_socket_source);
      component_source->socket_sources =
          g_slist_delete_link (component_source->socket_sources, childl);
    }

    childl = next;
  }


  /* Update the age. */
  component_source->component_socket_sources_age = component->socket_sources_age;

 done:

  agent_unlock_and_emit (agent);
  g_object_unref (agent);

  /* We can’t be sure if the ComponentSource itself needs to be dispatched until
   * poll() is called on all the child sources. */
  return FALSE;
}