Example #1
0
static gboolean
nice_output_stream_close (GOutputStream *stream, GCancellable *cancellable,
    GError **error)
{
  NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
  NiceComponent *component = NULL;
  NiceStream *_stream = NULL;
  NiceAgent *agent;  /* owned */

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

  agent_lock ();

  /* Shut down the write side of the pseudo-TCP stream. */
  if (agent_find_component (agent, priv->stream_id, priv->component_id,
          &_stream, &component) && agent->reliable &&
      !pseudo_tcp_socket_is_closed (component->tcp)) {
    pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_WR);
  }

  agent_unlock ();

  g_object_unref (agent);

  return TRUE;
}
Example #2
0
static gboolean priv_discovery_tick (gpointer pointer)
{
  NiceAgent *agent = pointer;
  gboolean ret;

  agent_lock();
  if (g_source_is_destroyed (g_main_current_source ())) {
    nice_debug ("Source was destroyed. "
        "Avoided race condition in priv_discovery_tick");
    agent_unlock ();
    return FALSE;
  }

  ret = priv_discovery_tick_unlocked (pointer);
  if (ret == FALSE) {
    if (agent->discovery_timer_source != NULL) {
      g_source_destroy (agent->discovery_timer_source);
      g_source_unref (agent->discovery_timer_source);
      agent->discovery_timer_source = NULL;
    }
  }
  agent_unlock_and_emit (agent);

  return ret;
}
Example #3
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;
}
Example #4
0
static gboolean
nice_input_stream_is_readable (GPollableInputStream *stream)
{
  NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
  Component *component = NULL;
  Stream *_stream = NULL;
  gboolean retval = FALSE;
  GSList *i;
  NiceAgent *agent;  /* owned */

  /* Closed streams are not readable. */
  if (g_input_stream_is_closed (G_INPUT_STREAM (stream)))
    return FALSE;

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

  agent_lock (agent);

  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 it’s a reliable agent, see if there’s any pending data in the pseudo-TCP
   * buffer. */
  if (agent->reliable &&
      pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) {
    retval = TRUE;
    goto done;
  }

  /* Check whether any of the component’s FDs are pollable. */
  for (i = component->socket_sources; i != NULL; i = i->next) {
    SocketSource *socket_source = i->data;
    NiceSocket *nicesock = socket_source->socket;

    if (g_socket_condition_check (nicesock->fileno, G_IO_IN) != 0) {
      retval = TRUE;
      break;
    }
  }

done:
  agent_unlock (agent);

  g_object_unref (agent);

  return retval;
}
Example #5
0
static gboolean
socket_send_more (
  GSocket *gsocket,
  GIOCondition condition,
  gpointer data)
{
  NiceSocket *sock = (NiceSocket *) data;
  TcpPriv *priv = sock->priv;

  agent_lock (NULL);

  if (g_source_is_destroyed (g_main_current_source ())) {
    nice_debug ("Source was destroyed. "
        "Avoided race condition in tcp-bsd.c:socket_send_more");
    agent_unlock (NULL);
    return FALSE;
  }

  /* connection hangs up or queue was emptied */
  if (condition & G_IO_HUP ||
      nice_socket_flush_send_queue_to_socket (sock->fileno,
          &priv->send_queue)) {
    g_source_destroy (priv->io_source);
    g_source_unref (priv->io_source);
    priv->io_source = NULL;

    agent_unlock (NULL);

    if (priv->writable_cb)
      priv->writable_cb (sock, priv->writable_data);

    return FALSE;
  }

  agent_unlock (NULL);
  return TRUE;
}
Example #6
0
static gboolean
nice_output_stream_is_writable (GPollableOutputStream *stream)
{
  NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
  NiceComponent *component = NULL;
  NiceStream *_stream = NULL;
  gboolean retval = FALSE;
  NiceAgent *agent;  /* owned */

  /* Closed streams are not writeable. */
  if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
    return FALSE;

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

  agent_lock ();

  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->selected_pair.local != NULL) {
    NiceSocket *sockptr = component->selected_pair.local->sockptr;

    /* If it’s a reliable agent, see if there’s any space in the pseudo-TCP
     * output buffer. */
    if (!nice_socket_is_reliable (sockptr)) {
      retval = pseudo_tcp_socket_can_send (component->tcp);
    } else {
      retval = (g_socket_condition_check (sockptr->fileno, G_IO_OUT) != 0);
    }
  }

done:
  agent_unlock ();

  g_object_unref (agent);

  return retval;
}
Example #7
0
static gboolean
socket_send_more (
  GSocket *gsocket,
  GIOCondition condition,
  gpointer data)
{
  NiceSocket *sock = (NiceSocket *) data;
  TcpPriv *priv = sock->priv;
  struct to_be_sent *tbs = NULL;
  GError *gerr = NULL;

  agent_lock ();

  if (g_source_is_destroyed (g_main_current_source ())) {
    nice_debug ("Source was destroyed. "
        "Avoided race condition in tcp-bsd.c:socket_send_more");
    agent_unlock ();
    return FALSE;
  }

  while ((tbs = g_queue_pop_head (&priv->send_queue)) != NULL) {
    int ret;

    if(condition & G_IO_HUP) {
      /* connection hangs up */
      ret = -1;
    } else {
      GOutputVector local_bufs = { tbs->buf, tbs->length };
      ret = g_socket_send_message (sock->fileno, NULL, &local_bufs, 1, NULL, 0,
          G_SOCKET_MSG_NONE, NULL, &gerr);
    }

    if (ret < 0) {
      if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
        GOutputVector local_buf = { tbs->buf, tbs->length };
        NiceOutputMessage local_message = {&local_buf, 1};

        add_to_be_sent (sock, &local_message, 0, local_buf.size, TRUE);
        free_to_be_sent (tbs);
        g_error_free (gerr);
        break;
      }
      g_clear_error (&gerr);
    } else if (ret < (int) tbs->length) {
      GOutputVector local_buf = { tbs->buf + ret, tbs->length - ret };
      NiceOutputMessage local_message = {&local_buf, 1};

      add_to_be_sent (sock, &local_message, 0, local_buf.size, TRUE);
      free_to_be_sent (tbs);
      break;
    }

    free_to_be_sent (tbs);
  }

  if (g_queue_is_empty (&priv->send_queue)) {
    g_source_destroy (priv->io_source);
    g_source_unref (priv->io_source);
    priv->io_source = NULL;

    agent_unlock ();
    return FALSE;
  }

  agent_unlock ();
  return TRUE;
}