Ejemplo n.º 1
0
static gboolean
web_socket_client_handshake (WebSocketConnection *conn,
                             GByteArray *incoming)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (conn);
  return parse_handshake_response (self, conn, incoming);
}
Ejemplo n.º 2
0
static void
on_connect_to_uri (GObject *source,
                   GAsyncResult *result,
                   gpointer user_data)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (user_data);
  WebSocketConnection *conn = WEB_SOCKET_CONNECTION (user_data);
  GSocketConnection *connection;
  GError *error = NULL;

  connection = g_socket_client_connect_to_uri_finish (G_SOCKET_CLIENT (source),
                                                      result, &error);

  if (error == NULL)
    {
      _web_socket_connection_take_io_stream (conn, G_IO_STREAM (connection));
      request_handshake (self, conn);
    }
  else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
    {
      g_error_free (error);
    }
  else
    {
      _web_socket_connection_error_and_close (conn, error, TRUE);
    }

  g_object_unref (self);
}
Ejemplo n.º 3
0
static void
on_web_socket_open (WebSocketConnection *connection,
                    gpointer user_data)
{
  CockpitWebSocketStream *self = COCKPIT_WEB_SOCKET_STREAM (user_data);
  CockpitChannel *channel = COCKPIT_CHANNEL (user_data);
  JsonObject *object;
  JsonObject *headers;
  GHashTableIter iter;
  gpointer key, value;

  headers = json_object_new ();

  g_hash_table_iter_init (&iter, web_socket_client_get_headers (WEB_SOCKET_CLIENT (self->client)));
  while (g_hash_table_iter_next (&iter, &key, &value))
    json_object_set_string_member (headers, key, value);

  object = json_object_new ();
  json_object_set_object_member (object, "headers", headers);

  cockpit_channel_control (channel, "response", object);
  json_object_unref (object);

  cockpit_channel_ready (channel, NULL);
}
Ejemplo n.º 4
0
static gpointer
on_idle_do_handshake (gpointer user_data)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (user_data);
  WebSocketConnection *conn = WEB_SOCKET_CONNECTION (user_data);
  g_source_unref (self->idle_start);
  self->idle_start = NULL;
  request_handshake (self, conn);
  return FALSE;
}
Ejemplo n.º 5
0
static void
web_socket_client_close (WebSocketConnection *conn)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (conn);

  if (self->cancellable)
    g_cancellable_cancel (self->cancellable);
  if (self->idle_start)
    {
      g_source_destroy (self->idle_start);
      g_source_unref (self->idle_start);
    }
}
Ejemplo n.º 6
0
static void
web_socket_client_finalize (GObject *object)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (object);

  g_strfreev (self->possible_protocols);
  g_free (self->accept_key);
  if (self->include_headers)
    g_hash_table_unref (self->include_headers);
  if (self->cancellable)
    g_object_unref (self->cancellable);
  g_assert (self->idle_start == NULL);

  G_OBJECT_CLASS (web_socket_client_parent_class)->finalize (object);
}
Ejemplo n.º 7
0
static void
web_socket_client_constructed (GObject *object)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (object);
  WebSocketConnection *conn = WEB_SOCKET_CONNECTION (object);
  GSocketClient *client;
  const gchar *url;
  guint16 default_port;
  gchar *scheme;

  G_OBJECT_CLASS (web_socket_client_parent_class)->constructed (object);

  if (web_socket_connection_get_io_stream (conn))
    {
      /* Start handshake from the main context */
      self->idle_start = g_idle_source_new ();
      g_source_set_priority (self->idle_start, G_PRIORITY_HIGH);
      g_source_set_callback (self->idle_start, (GSourceFunc)on_idle_do_handshake,
                             self, NULL);
      g_source_attach (self->idle_start, _web_socket_connection_get_main_context (conn));
    }
  else
    {
      client = g_socket_client_new ();
      self->cancellable = g_cancellable_new ();

      url = web_socket_connection_get_url (WEB_SOCKET_CONNECTION (self));
      scheme = g_uri_parse_scheme (url);
      if (scheme && (g_str_equal (scheme, "wss") || g_str_equal (scheme, "https")))
        {
          g_socket_client_set_tls (client, TRUE);
          default_port = 443;
        }
      else
        {
          default_port = 80;
        }
      g_free (scheme);

      g_socket_client_connect_to_uri_async (client, url, default_port,
                                            self->cancellable, on_connect_to_uri,
                                            g_object_ref (self));
      g_object_unref (client);
    }
}
Ejemplo n.º 8
0
static void
web_socket_client_set_property (GObject *object,
                                guint prop_id,
                                const GValue *value,
                                GParamSpec *pspec)
{
  WebSocketClient *self = WEB_SOCKET_CLIENT (object);

  switch (prop_id)
    {
    case PROP_PROTOCOLS:
      g_return_if_fail (self->handshake_started == FALSE);
      g_strfreev (self->possible_protocols);
      self->possible_protocols = g_value_dup_boxed (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
Ejemplo n.º 9
0
static void
on_socket_connect (GObject *object,
                   GAsyncResult *result,
                   gpointer user_data)
{
  CockpitWebSocketStream *self = COCKPIT_WEB_SOCKET_STREAM (user_data);
  CockpitChannel *channel = COCKPIT_CHANNEL (self);
  const gchar *problem = "protocol-error";
  gchar **protocols = NULL;
  GList *l, *names = NULL;
  GError *error = NULL;
  JsonObject *options;
  JsonObject *headers;
  const gchar *value;
  JsonNode *node;
  GIOStream *io;

  io = cockpit_connect_stream_finish (result, &error);
  if (error)
    {
      problem = cockpit_stream_problem (error, self->origin, "couldn't connect",
                                        cockpit_channel_close_options (channel));
      cockpit_channel_close (channel, problem);
      goto out;
    }

  options = cockpit_channel_get_options (channel);

  if (!cockpit_json_get_strv (options, "protocols", NULL, &protocols))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: invalid \"protocol\" value in WebSocket stream request", self->origin);
      goto out;
    }

  if (G_IS_TLS_CONNECTION (io))
    {
      self->sig_accept_cert =  g_signal_connect (G_TLS_CONNECTION (io),
                                                 "accept-certificate",
                                                 G_CALLBACK (on_rejected_certificate),
                                                 self);
    }
  else
    {
      self->sig_accept_cert = 0;
    }

  self->client = web_socket_client_new_for_stream (self->url, self->origin, (const gchar **)protocols, io);

  node = json_object_get_member (options, "headers");
  if (node)
    {
      if (!JSON_NODE_HOLDS_OBJECT (node))
        {
          cockpit_channel_fail (channel, "protocol-error",
                                "%s: invalid \"headers\" field in WebSocket stream request", self->origin);
          goto out;
        }

      headers = json_node_get_object (node);
      names = json_object_get_members (headers);
      for (l = names; l != NULL; l = g_list_next (l))
        {
          node = json_object_get_member (headers, l->data);
          if (!node || !JSON_NODE_HOLDS_VALUE (node) || json_node_get_value_type (node) != G_TYPE_STRING)
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: invalid header value in WebSocket stream request: %s",
                                    self->origin, (gchar *)l->data);
              goto out;
            }
          value = json_node_get_string (node);

          g_debug ("%s: sending header: %s %s", self->origin, (gchar *)l->data, value);
          web_socket_client_include_header (WEB_SOCKET_CLIENT (self->client), l->data, value);
        }
    }

  self->sig_open = g_signal_connect (self->client, "open", G_CALLBACK (on_web_socket_open), self);
  self->sig_message = g_signal_connect (self->client, "message", G_CALLBACK (on_web_socket_message), self);
  self->sig_closing = g_signal_connect (self->client, "closing", G_CALLBACK (on_web_socket_closing), self);
  self->sig_close = g_signal_connect (self->client, "close", G_CALLBACK (on_web_socket_close), self);
  self->sig_error = g_signal_connect (self->client, "error", G_CALLBACK (on_web_socket_error), self);

  problem = NULL;

out:
  g_clear_error (&error);
  g_strfreev (protocols);
  if (io)
    g_object_unref (io);
  g_list_free (names);
}