Ejemplo n.º 1
0
gssize
g_tls_connection_base_write (GTlsConnectionBase  *tls,
			     const void          *buffer,
			     gsize                count,
			     gboolean             blocking,
			     GCancellable        *cancellable,
			     GError             **error)
{
  GTlsConnectionBaseStatus status;
  gssize nwrote;

  do
    {
      if (!claim_op (tls, G_TLS_CONNECTION_BASE_OP_WRITE,
		     blocking, cancellable, error))
	return -1;

      status = G_TLS_CONNECTION_BASE_GET_CLASS (tls)->
	write_fn (tls, buffer, count, blocking, &nwrote, cancellable, error);

      yield_op (tls, G_TLS_CONNECTION_BASE_OP_WRITE, status);
    }
  while (status == G_TLS_CONNECTION_BASE_REHANDSHAKE);

  if (status == G_TLS_CONNECTION_BASE_OK)
    return nwrote;
  else
    return -1;
}
Ejemplo n.º 2
0
static void
implicit_handshake_completed (GObject      *object,
			      GAsyncResult *result,
			      gpointer      user_data)
{
  GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (object);

  g_mutex_lock (&tls->op_mutex);
  tls->need_finish_handshake = TRUE;
  g_mutex_unlock (&tls->op_mutex);

  yield_op (tls, G_TLS_CONNECTION_BASE_OP_HANDSHAKE,
	    G_TLS_CONNECTION_BASE_OK);
}
Ejemplo n.º 3
0
static gboolean
do_implicit_handshake (GTlsConnectionBase  *tls,
		       gboolean             blocking,
		       GCancellable        *cancellable,
		       GError             **error)
{
  /* We have op_mutex */

  tls->implicit_handshake = g_task_new (tls, cancellable,
					implicit_handshake_completed,
					NULL);
  g_task_set_source_tag (tls->implicit_handshake, do_implicit_handshake);

  if (blocking)
    {
      GError *my_error = NULL;
      gboolean success;

      g_mutex_unlock (&tls->op_mutex);
      g_task_run_in_thread_sync (tls->implicit_handshake,
				 handshake_thread);
      success = finish_handshake (tls,
				  tls->implicit_handshake,
				  &my_error);
      g_clear_object (&tls->implicit_handshake);
      yield_op (tls, G_TLS_CONNECTION_BASE_OP_HANDSHAKE,
		G_TLS_CONNECTION_BASE_OK);
      g_mutex_lock (&tls->op_mutex);

      if (my_error)
	g_propagate_error (error, my_error);
      return success;
    }
  else
    {
      g_task_run_in_thread (tls->implicit_handshake,
			    handshake_thread);

      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
			   _("Operation would block"));
      return FALSE;
    }
}
Ejemplo n.º 4
0
gssize
g_tls_connection_base_read (GTlsConnectionBase  *tls,
			    void                *buffer,
			    gsize                count,
			    gboolean             blocking,
			    GCancellable        *cancellable,
			    GError             **error)
{
  GTlsConnectionBaseStatus status;
  gssize nread;

  do
    {
      if (!claim_op (tls, G_TLS_CONNECTION_BASE_OP_READ,
		     blocking, cancellable, error))
	return -1;

      if (tls->app_data_buf && !tls->handshaking)
	{
	  nread = MIN (count, tls->app_data_buf->len);
	  memcpy (buffer, tls->app_data_buf->data, nread);
	  if (nread == tls->app_data_buf->len)
	    g_clear_pointer (&tls->app_data_buf, g_byte_array_unref);
	  else
	    g_byte_array_remove_range (tls->app_data_buf, 0, nread);
	  status = G_TLS_CONNECTION_BASE_OK;
	}
      else
	{
	  status = G_TLS_CONNECTION_BASE_GET_CLASS (tls)->
	    read_fn (tls, buffer, count, blocking, &nread, cancellable, error);
	}

      yield_op (tls, G_TLS_CONNECTION_BASE_OP_READ, status);
    }
  while (status == G_TLS_CONNECTION_BASE_REHANDSHAKE);

  if (status == G_TLS_CONNECTION_BASE_OK)
    return nread;
  else
    return -1;
}
Ejemplo n.º 5
0
static void
async_handshake_thread (GTask        *task,
			gpointer      object,
			gpointer      task_data,
			GCancellable *cancellable)
{
  GTlsConnectionBase *tls = object;

  handshake_thread (task, object, task_data, cancellable);

  g_mutex_lock (&tls->op_mutex);
  tls->need_finish_handshake = TRUE;
  /* yield_op will clear handshaking too, but we don't want the
   * connection to be briefly "handshaking && need_finish_handshake"
   * after we unlock the mutex.
   */
  tls->handshaking = FALSE;
  g_mutex_unlock (&tls->op_mutex);

  yield_op (tls, G_TLS_CONNECTION_BASE_OP_HANDSHAKE,
	    G_TLS_CONNECTION_BASE_OK);
}
Ejemplo n.º 6
0
static gboolean
g_tls_connection_base_handshake (GTlsConnection   *conn,
				 GCancellable     *cancellable,
				 GError          **error)
{
  GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (conn);
  GTask *task;
  gboolean success;
  GError *my_error = NULL;

  task = g_task_new (conn, cancellable, NULL, NULL);
  g_task_set_source_tag (task, g_tls_connection_base_handshake);
  g_task_run_in_thread_sync (task, handshake_thread);
  success = finish_handshake (tls, task, &my_error);
  g_object_unref (task);

  yield_op (tls, G_TLS_CONNECTION_BASE_OP_HANDSHAKE,
	    G_TLS_CONNECTION_BASE_OK);

  if (my_error)
    g_propagate_error (error, my_error);
  return success;
}
Ejemplo n.º 7
0
static void test_case_yield_op(
  Thread_Control *executing,
  Scheduler_SMP_Node *executing_node,
  Thread_Control *other,
  Scheduler_SMP_Node_state start_state,
  Scheduler_SMP_Node_state new_state
)
{
  Thread_Control *needs_help;

  _Thread_Change_priority(executing, 4, false);
  _Thread_Change_priority(other, 4, false);

  switch (start_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      switch (new_state) {
        case SCHEDULER_SMP_NODE_SCHEDULED:
          _Thread_Change_priority(executing, 2, false);
          _Thread_Change_priority(other, 3, false);
          break;
        case SCHEDULER_SMP_NODE_READY:
          _Thread_Change_priority(executing, 2, false);
          _Thread_Change_priority(other, 2, false);
          break;
        default:
          rtems_test_assert(0);
          break;
      }
      break;
    case SCHEDULER_SMP_NODE_READY:
      switch (new_state) {
        case SCHEDULER_SMP_NODE_SCHEDULED:
          rtems_test_assert(0);
          break;
        case SCHEDULER_SMP_NODE_READY:
          _Thread_Change_priority(executing, 3, false);
          _Thread_Change_priority(other, 2, false);
          break;
        default:
          rtems_test_assert(0);
          break;
      }
      break;
    default:
      rtems_test_assert(0);
      break;
  }
  rtems_test_assert(executing_node->state == start_state);

  needs_help = yield_op(executing);
  rtems_test_assert(executing_node->state == new_state);

  if (start_state != new_state) {
    switch (start_state) {
      case SCHEDULER_SMP_NODE_SCHEDULED:
        rtems_test_assert(needs_help == executing);
        break;
      case SCHEDULER_SMP_NODE_READY:
        rtems_test_assert(needs_help == other);
        break;
      default:
        rtems_test_assert(0);
        break;
    }
  } else {
    rtems_test_assert(needs_help == NULL);
  }
}
Ejemplo n.º 8
0
gboolean
g_tls_connection_base_close_internal (GIOStream     *stream,
                                      GTlsDirection  direction,
                                      GCancellable  *cancellable,
                                      GError       **error)
{
  GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (stream);
  GTlsConnectionBaseOp op;
  GTlsConnectionBaseStatus status;
  gboolean success = TRUE;
  GError *close_error = NULL, *stream_error = NULL;

  /* This can be called from g_io_stream_close(), g_input_stream_close() or
   * g_output_stream_close(). In all cases, we only do the close_fn() for
   * writing. The difference is how we set the flags on this class and how
   * the underlying stream is closed.
   */

  g_return_val_if_fail (direction != G_TLS_DIRECTION_NONE, FALSE);

  if (direction == G_TLS_DIRECTION_BOTH)
    op = G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH;
  else if (direction == G_TLS_DIRECTION_READ)
    op = G_TLS_CONNECTION_BASE_OP_CLOSE_READ;
  else
    op = G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE;

  if (!claim_op (tls, op, TRUE, cancellable, error))
    return FALSE;

  if (tls->ever_handshaked && !tls->write_closed &&
      direction & G_TLS_DIRECTION_WRITE)
    {
      status = G_TLS_CONNECTION_BASE_GET_CLASS (tls)->
	close_fn (tls, cancellable, &close_error);

      tls->write_closed = TRUE;
    }
  else
    status = G_TLS_CONNECTION_BASE_OK;

  if (!tls->read_closed && direction & G_TLS_DIRECTION_READ)
    tls->read_closed = TRUE;

  /* Close the underlying streams. Do this even if the close_fn() call failed,
   * as the parent GIOStream will have set its internal closed flag and hence
   * this implementation will never be called again. */
  if (direction == G_TLS_DIRECTION_BOTH)
    success = g_io_stream_close (tls->base_io_stream,
                                 cancellable, &stream_error);
  else if (direction & G_TLS_DIRECTION_READ)
    success = g_input_stream_close (g_io_stream_get_input_stream (tls->base_io_stream),
                                    cancellable, &stream_error);
  else if (direction & G_TLS_DIRECTION_WRITE)
    success = g_output_stream_close (g_io_stream_get_output_stream (tls->base_io_stream),
                                     cancellable, &stream_error);

  yield_op (tls, op, status);

  /* Propagate errors. */
  if (status != G_TLS_CONNECTION_BASE_OK)
    {
      g_propagate_error (error, close_error);
      g_clear_error (&stream_error);
    }
  else if (!success)
    {
      g_propagate_error (error, stream_error);
      g_clear_error (&close_error);
    }

  return success && status == G_TLS_CONNECTION_BASE_OK;
}