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; }
/** * 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; }
static void nice_component_init (NiceComponent *component) { g_atomic_int_inc (&n_components_created); nice_debug ("Created NiceComponent (%u created, %u destroyed)", n_components_created, n_components_destroyed); component->id = 0; component->state = NICE_COMPONENT_STATE_DISCONNECTED; component->restart_candidate = NULL; component->tcp = NULL; component->agent = NULL; component->stream = NULL; g_mutex_init (&component->io_mutex); g_queue_init (&component->pending_io_messages); component->io_callback_id = 0; component->own_ctx = g_main_context_new (); component->stop_cancellable = g_cancellable_new (); component->stop_cancellable_source = g_cancellable_source_new (component->stop_cancellable); g_source_set_dummy_callback (component->stop_cancellable_source); g_source_attach (component->stop_cancellable_source, component->own_ctx); component->ctx = g_main_context_ref (component->own_ctx); /* Start off with a fresh main context and all I/O paused. This * will be updated when nice_agent_attach_recv() or nice_agent_recv_messages() * are called. */ nice_component_set_io_context (component, NULL); nice_component_set_io_callback (component, NULL, NULL, NULL, 0, NULL); g_queue_init (&component->queued_tcp_packets); }
/** * 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; }
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); }
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; }
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; }
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; }
int main(void) { NiceAgent *lagent = NULL, *ragent = NULL; GThread *stun_thread = NULL; NiceAddress baseaddr; GSource *src; int sock; global_cancellable = g_cancellable_new (); src = g_cancellable_source_new (global_cancellable); g_source_set_dummy_callback (src); g_source_attach (src, NULL); sock = listen_socket (&stun_port); if (sock == -1) { g_assert_not_reached (); } stun_thread = g_thread_new ("listen for STUN requests", stun_thread_func, GINT_TO_POINTER (sock)); // Once the the thread is forked, we want to listen for a signal // that the socket was opened successfully g_mutex_lock (stun_thread_mutex_ptr); g_cond_wait (stun_thread_signal_ptr, stun_thread_mutex_ptr); lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245); ragent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245); g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL); g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL); g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL); g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL); g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL); g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL); g_object_set (G_OBJECT (lagent), "stun-server", "127.0.0.1", NULL); g_object_set (G_OBJECT (lagent), "stun-server-port", stun_port, NULL); g_object_set_data (G_OBJECT (lagent), "other-agent", ragent); g_object_set_data (G_OBJECT (ragent), "other-agent", lagent); g_assert (nice_address_set_from_string (&baseaddr, "127.0.0.1")); nice_agent_add_local_address (lagent, &baseaddr); nice_agent_add_local_address (ragent, &baseaddr); g_signal_connect(G_OBJECT(lagent), "candidate-gathering-done", G_CALLBACK(cb_candidate_gathering_done), LEFT_AGENT); g_signal_connect(G_OBJECT(ragent), "candidate-gathering-done", G_CALLBACK(cb_candidate_gathering_done), RIGHT_AGENT); g_signal_connect(G_OBJECT(lagent), "component-state-changed", G_CALLBACK(cb_component_state_changed), LEFT_AGENT); g_signal_connect(G_OBJECT(ragent), "component-state-changed", G_CALLBACK(cb_component_state_changed), RIGHT_AGENT); standard_test (lagent, ragent); bad_credentials_test (lagent, ragent); bad_candidate_test (lagent, ragent); new_candidate_test (lagent, ragent); // Do this to make sure the STUN thread exits exit_stun_thread = TRUE; drop_stun_packets = TRUE; send_dummy_data (); g_object_add_weak_pointer (G_OBJECT (lagent), (gpointer *) &lagent); g_object_add_weak_pointer (G_OBJECT (ragent), (gpointer *) &ragent); g_object_unref (lagent); g_object_unref (ragent); g_thread_join (stun_thread); g_object_unref (global_cancellable); g_source_destroy (src); g_source_unref (src); WAIT_UNTIL_UNSET (lagent, NULL); WAIT_UNTIL_UNSET (ragent, NULL); return 0; }