Exemple #1
0
/**
 * cockpit_channel_close:
 * @self: a channel
 * @problem: the problem or NULL
 *
 * Close the channel. This can be called mulitple times.
 *
 * It may be that the channel doesn't close immediately.
 * The channel will emit the CockpitChannel::closed signal when the
 * channel actually closes.
 *
 * If this is called immediately after or during construction then
 * the closing will happen after the main loop so that handlers
 * can connect appropriately.
 *
 * A @problem of NULL represents an orderly close.
 */
void
cockpit_channel_close (CockpitChannel *self,
                       const gchar *problem)
{
  CockpitChannelClass *klass;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));

  /* No further messages should be received */
  if (self->priv->recv_sig)
    g_signal_handler_disconnect (self->priv->transport, self->priv->recv_sig);
  self->priv->recv_sig = 0;

  if (self->priv->control_sig)
    g_signal_handler_disconnect (self->priv->transport, self->priv->control_sig);
  self->priv->control_sig = 0;

  if (self->priv->close_sig)
    g_signal_handler_disconnect (self->priv->transport, self->priv->close_sig);
  self->priv->close_sig = 0;

  klass = COCKPIT_CHANNEL_GET_CLASS (self);
  g_assert (klass->close != NULL);
  self->priv->emitted_close = TRUE;
  (klass->close) (self, problem);
}
Exemple #2
0
/**
 * cockpit_channel_control:
 * @self: the channel
 * @command: the control command
 * @options: optional control message or NULL
 *
 * Send a control message to the other side.
 *
 * If @options is not NULL, then it may be modified by this code.
 *
 * With @command of "done" will send an EOF to the other side. This
 * should only be called once. Whether an EOF should be sent or not
 * depends on the payload type.
 */
void
cockpit_channel_control (CockpitChannel *self,
                         const gchar *command,
                         JsonObject *options)
{
  JsonObject *object;
  GBytes *message;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));
  g_return_if_fail (command != NULL);

  if (g_str_equal (command, "done"))
    {
      g_return_if_fail (self->priv->sent_done == FALSE);
      self->priv->sent_done = TRUE;
    }

  if (options)
    object = json_object_ref (options);
  else
    object = json_object_new ();

  json_object_set_string_member (object, "command", command);
  json_object_set_string_member (object, "channel", self->priv->id);

  message = cockpit_json_write_bytes (object);
  json_object_unref (object);

  cockpit_transport_send (self->priv->transport, NULL, message);
  g_bytes_unref (message);
}
Exemple #3
0
/*
 * cockpit_channel_fail:
 * @self: a channel
 * @problem: the problem
 *
 * Close the channel with a @problem. In addition a "message" field
 * will be set on the channel, using the @format argument to bulid
 * the message. The message will also be logged.
 *
 * See cockpit_channel_close() for further info.
 */
void
cockpit_channel_fail (CockpitChannel *self,
                      const gchar *problem,
                      const gchar *format,
                      ...)
{
  JsonObject *options;
  gchar *message;
  va_list va;

  g_return_if_fail (problem != NULL);
  g_return_if_fail (COCKPIT_IS_CHANNEL (self));

  va_start (va, format);
  message = g_strdup_vprintf (format, va);
  va_end (va);

  options = cockpit_channel_close_options (self);
  if (!json_object_has_member (options, "message"))
    json_object_set_string_member (options, "message", message);
  g_message ("%s: %s", self->priv->id, message);
  g_free (message);

  cockpit_channel_close (self, problem);
}
Exemple #4
0
/**
 * cockpit_channel_close_options
 * @self: a channel
 *
 * Called by implementations to get the channel's close options.
 *
 * Returns: (transfer none): the close options, should not be NULL
 */
JsonObject *
cockpit_channel_close_options (CockpitChannel *self)
{
  g_return_val_if_fail (COCKPIT_IS_CHANNEL (self), NULL);
  if (!self->priv->close_options)
    self->priv->close_options = json_object_new ();
  return self->priv->close_options;
}
Exemple #5
0
/**
 * cockpit_channel_control:
 * @self: the channel
 * @command: the control command
 * @options: optional control message or NULL
 *
 * Send a control message to the other side.
 *
 * If @options is not NULL, then it may be modified by this code.
 *
 * With @command of "done" will send an EOF to the other side. This
 * should only be called once. Whether an EOF should be sent or not
 * depends on the payload type.
 */
void
cockpit_channel_control (CockpitChannel *self,
                         const gchar *command,
                         JsonObject *options)
{
  JsonObject *object;
  GBytes *message;
  const gchar *problem;
  gchar *problem_copy = NULL;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));
  g_return_if_fail (command != NULL);

  if (g_str_equal (command, "done"))
    {
      g_return_if_fail (self->priv->sent_done == FALSE);
      self->priv->sent_done = TRUE;
    }

  /* If closing save the close options
   * and let close send the message */
  else if (g_str_equal (command, "close"))
    {
      if (!self->priv->close_options)
        {
          /* Ref for close_options, freed in parent */
          self->priv->close_options = json_object_ref (options);
        }

      if (!cockpit_json_get_string (options, "problem", NULL, &problem))
        problem = NULL;

      /* Use a problem copy so it out lasts the value in close_options */
      problem_copy = g_strdup (problem);
      cockpit_channel_close (self, problem_copy);
      goto out;
    }

  if (options)
    object = json_object_ref (options);
  else
    object = json_object_new ();

  json_object_set_string_member (object, "command", command);
  json_object_set_string_member (object, "channel", self->priv->id);

  message = cockpit_json_write_bytes (object);
  json_object_unref (object);

  cockpit_transport_send (self->priv->transport, NULL, message);
  g_bytes_unref (message);

out:
  g_free (problem_copy);
}
Exemple #6
0
/**
 * cockpit_channel_close_int_option:
 * @self: a channel
 * @name: the option name
 * @value: the value to add
 *
 * Add a value to the close message for this channel. This must
 * be called before the cockpit_channel_close base class
 * implementation.
 */
void
cockpit_channel_close_int_option (CockpitChannel *self,
                                  const gchar *name,
                                  gint64 value)
{
  g_return_if_fail (COCKPIT_IS_CHANNEL (self));
  g_return_if_fail (name != NULL);

  if (!self->priv->close_options)
    self->priv->close_options = json_object_new ();
  json_object_set_int_member (self->priv->close_options, name, value);
}
Exemple #7
0
/**
 * cockpit_channel_close:
 * @self: a channel
 * @problem: the problem or NULL
 *
 * Close the channel. This can be called mulitple times.
 *
 * It may be that the channel doesn't close immediately.
 * The channel will emit the CockpitChannel::closed signal when the
 * channel actually closes.
 *
 * A @reason of NULL represents an orderly close.
 */
void
cockpit_channel_close (CockpitChannel *self,
                       const gchar *reason)
{
  CockpitChannelClass *klass;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));

  klass = COCKPIT_CHANNEL_GET_CLASS (self);
  g_assert (klass->close != NULL);
  (klass->close) (self, reason);
}
Exemple #8
0
void
cockpit_channel_close_obj_option (CockpitChannel *self,
                                  const gchar *name,
                                  JsonObject *object)
{
  g_return_if_fail (COCKPIT_IS_CHANNEL (self));
  g_return_if_fail (name != NULL);
  g_return_if_fail (object != NULL);

  if (!self->priv->close_options)
    self->priv->close_options = json_object_new ();
  json_object_set_object_member (self->priv->close_options, name,
                                 json_object_ref (object));
}
Exemple #9
0
/**
 * cockpit_channel_prepare:
 * @self: the channel
 *
 * Usually this is automatically called after the channel is
 * created and control returns to the mainloop. However you
 * can preempt that by calling this function.
 */
void
cockpit_channel_prepare (CockpitChannel *self)
{
  CockpitChannelClass *klass;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));

  if (!self->priv->prepare_tag)
    return;

  g_source_remove (self->priv->prepare_tag);
  self->priv->prepare_tag = 0;

  if (!self->priv->emitted_close)
    {
      klass = COCKPIT_CHANNEL_GET_CLASS (self);
      g_assert (klass->prepare);
      (klass->prepare) (self);
    }
}
Exemple #10
0
/**
 * cockpit_channel_done:
 * @self: the channel
 *
 * Send an EOF to the other side. This should only be called once.
 * Whether an EOF should be sent or not depends on the payload type.
 */
void
cockpit_channel_done (CockpitChannel *self)
{
  JsonObject *object;
  GBytes *message;

  g_return_if_fail (COCKPIT_IS_CHANNEL (self));
  g_return_if_fail (self->priv->sent_done == FALSE);

  self->priv->sent_done = TRUE;

  object = json_object_new ();
  json_object_set_string_member (object, "command", "done");
  json_object_set_string_member (object, "channel", self->priv->id);

  message = cockpit_json_write_bytes (object);
  json_object_unref (object);

  cockpit_transport_send (self->priv->transport, NULL, message);
  g_bytes_unref (message);
}
Exemple #11
0
/**
 * cockpit_channel_get_id:
 * @self a channel
 *
 * Get the identifier for this channel.
 *
 * Returns: (transfer none): the identifier
 */
const gchar *
cockpit_channel_get_id (CockpitChannel *self)
{
  g_return_val_if_fail (COCKPIT_IS_CHANNEL (self), NULL);
  return self->priv->id;
}
Exemple #12
0
/**
 * cockpit_channel_get_option:
 * @self: a channel
 *
 * Called by implementations to get the channel's open options.
 *
 * Returns: (transfer none): the open options, should not be NULL
 */
JsonObject *
cockpit_channel_get_options (CockpitChannel *self)
{
  g_return_val_if_fail (COCKPIT_IS_CHANNEL (self), NULL);
  return self->priv->open_options;
}
Exemple #13
0
/**
 * cockpit_channel_get_transport:
 * @self: a channel
 *
 * Called by implementations to get the channel's transtport.
 *
 * Returns: (transfer none): the transport, should not be NULL
 */
CockpitTransport *
cockpit_channel_get_transport (CockpitChannel *self)
{
  g_return_val_if_fail (COCKPIT_IS_CHANNEL (self), NULL);
  return self->priv->transport;
}