From cf8bed1c40e2dbd84cf440a1a6222b73957f311f Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Mon, 15 Feb 2016 16:30:06 +0100 Subject: [PATCH] Rework MatrixHTTPClient in Vala --- .gitignore | 1 + src/Makefile.am | 3 +- src/matrix-http-client.c | 256 ------------------------------------ src/matrix-http-client.h | 51 ------- src/matrix-http-client.vala | 137 +++++++++++++++++++ 5 files changed, 139 insertions(+), 309 deletions(-) delete mode 100644 src/matrix-http-client.c delete mode 100644 src/matrix-http-client.h create mode 100644 src/matrix-http-client.vala diff --git a/.gitignore b/.gitignore index 77549bf..9ef1177 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ Makefile.in /src/matrix-client.c /src/matrix-enums.c /src/matrix-http-api.c +/src/matrix-http-client.c diff --git a/src/Makefile.am b/src/Makefile.am index 539e452..3273a95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,7 @@ libmatrix_glib_0_0_la_VALA_SOURCES = \ matrix-client.vala \ matrix-enums.vala \ matrix-http-api.vala \ + matrix-http-client.vala \ $(NULL) AM_CPPFLAGS += \ @@ -74,7 +75,6 @@ bin_PROGRAMS = test-api-client INST_H_SRC_FILES = \ matrix-types.h \ - matrix-http-client.h \ $(NULL) INST_H_BUILT_FILES = \ @@ -93,7 +93,6 @@ libmatrix_glib_0_0_la_SOURCES = \ matrix-types.c \ matrix-enumtypes.c \ utils.c \ - matrix-http-client.c \ $(INST_H_SRC_FILES) \ $(NULL) diff --git a/src/matrix-http-client.c b/src/matrix-http-client.c deleted file mode 100644 index 9604946..0000000 --- a/src/matrix-http-client.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ - -#include "matrix-http-client.h" - -/** - * SECTION:matrix-http-client - * @short_description: A HTTP based Matrix.org client - * @title: MatrixHTTPClient - * @stability: Unstable - * - * An event-driven client class to communicate with HTTP based - * Matrix.org servers. - */ - -/** - * MatrixHTTPClient: - * - * The client instance definition. - */ - -/** - * MatrixHTTPClientClass: - * - * Class definition for #MatrixHTTPClient. - */ - -typedef struct _MatrixHTTPClientPrivate { - gboolean polling; - guint event_timeout; -} MatrixHTTPClientPrivate; - -static void matrix_http_client_matrix_client_init(MatrixClientIface *iface); -static void i_begin_polling(MatrixClient *client, GError **error); - -G_DEFINE_TYPE_WITH_CODE(MatrixHTTPClient, matrix_http_client, MATRIX_TYPE_HTTP_API, - G_ADD_PRIVATE(MatrixHTTPClient) - G_IMPLEMENT_INTERFACE(MATRIX_TYPE_CLIENT, - matrix_http_client_matrix_client_init)); - -static void -cb_login(MatrixAPI *api, - const gchar *content_type, - JsonNode *json_content, - GByteArray *raw_content, - GError *error, - gpointer user_data) -{ - matrix_client_emit_login_finished(MATRIX_CLIENT(api), (error == NULL)); -} - -static void -i_login_with_password(MatrixClient *client, - const gchar *username, - const gchar *password, - GError **error) -{ - JsonBuilder *builder; - JsonNode *body; - - builder = json_builder_new(); - json_builder_begin_object(builder); - - json_builder_set_member_name(builder, "user"); - json_builder_add_string_value(builder, username); - - json_builder_set_member_name(builder, "password"); - json_builder_add_string_value(builder, password); - - json_builder_end_object(builder); - body = json_builder_get_root(builder); - g_object_unref(builder); - - matrix_api_login(MATRIX_API(client), - cb_login, NULL, - "m.login.password", body, - error); -} - -static void -cb_register_account(MatrixAPI *api, - const gchar *content_type, - JsonNode *json_content, - GByteArray *raw_content, - GError *error, - gpointer user_data) -{ - matrix_client_emit_login_finished(MATRIX_CLIENT(api), (error == NULL)); -} - -static void -i_register_with_password(MatrixClient *client, - const gchar *username, - const gchar *password, - GError **error) -{ - matrix_api_register_account(MATRIX_API(client), - cb_register_account, NULL, - MATRIX_ACCOUNT_KIND_USER, - FALSE, - username, password, - error); -} - -static void -i_logout(MatrixClient *client, GError **error) -{ - matrix_api_set_token(MATRIX_API(client), NULL); - matrix_api_set_refresh_token(MATRIX_API(client), NULL); - matrix_api_abort_pending(MATRIX_API(client)); -} - -static void -process_event(JsonArray *array, - guint idx, - JsonNode *event, - MatrixClient *client) -{} - -static void -cb_event_stream(MatrixAPI *api, - const gchar *content_type, - JsonNode *json_content, - GByteArray *raw_content, - GError *error, - gpointer user_data) -{ - MatrixHTTPClientPrivate *priv = matrix_http_client_get_instance_private( - MATRIX_HTTP_CLIENT(api)); - const gchar *end_token = NULL; - - if (!error) { - JsonObject *root_obj; - JsonNode *node; - - root_obj = json_node_get_object(json_content); - - if ((node = json_object_get_member(root_obj, "chunk")) != NULL) { - JsonArray *chunks = json_node_get_array(node); - - json_array_foreach_element(chunks, - (JsonArrayForeach)process_event, - api); - } - - if ((node = json_object_get_member(root_obj, "end")) != NULL) { - end_token = json_node_get_string(node); - } - } - - // Only continue polling if polling is still enabled, and there - // was no communication error during the last call - if (priv->polling - && (!error || error->code <= MATRIX_ERROR_M_MISSING_TOKEN)) { - priv->polling = FALSE; - - matrix_api_event_stream(api, - cb_event_stream, NULL, - end_token, priv->event_timeout, - NULL); - } -} - -static void -i_begin_polling(MatrixClient *client, GError **error) -{ - MatrixHTTPClientPrivate *priv = matrix_http_client_get_instance_private( - MATRIX_HTTP_CLIENT(client)); - GError *err = NULL; - - matrix_api_event_stream(MATRIX_API(client), - cb_event_stream, NULL, - NULL, priv->event_timeout, - &err); - - if (err) { - g_propagate_error(error, err); - - return; - } - - priv->polling = TRUE; -} - -static void -i_stop_polling(MatrixClient *client, gboolean cancel_ongoing, GError **error) -{ - MatrixHTTPClientPrivate *priv = matrix_http_client_get_instance_private( - MATRIX_HTTP_CLIENT(client)); - - priv->polling = FALSE; - - if (cancel_ongoing) { - matrix_api_abort_pending(MATRIX_API(client)); - } -} - -static void -matrix_http_client_matrix_client_init(MatrixClientIface *iface) -{ - iface->login_with_password = i_login_with_password; - iface->register_with_password = i_register_with_password; - iface->logout = i_logout; - iface->begin_polling = i_begin_polling; - iface->stop_polling = i_stop_polling; -} - -static void -matrix_http_client_init(MatrixHTTPClient *client) -{ - MatrixHTTPClientPrivate *priv = matrix_http_client_get_instance_private( - client); - - priv->polling = FALSE; - priv->event_timeout = 30000; -} - -static void -matrix_http_client_class_init(MatrixHTTPClientClass *klass) -{} - -/** - * matrix_http_client_new: - * @base_url: the base URL to use for API communication - * - * Creates a new #MatrixHTTPClient object. - * - * Returns: (transfer full): a new #MatrixHTTPClient. The object is - * cast to #MatrixClient for easier interface usage. - */ -MatrixClient * -matrix_http_client_new(const gchar *base_url) -{ - MatrixHTTPClient *client; - - client = g_object_new(MATRIX_TYPE_HTTP_CLIENT, - "base-url", base_url, - NULL); - - return MATRIX_CLIENT(client); -} diff --git a/src/matrix-http-client.h b/src/matrix-http-client.h deleted file mode 100644 index 7391726..0000000 --- a/src/matrix-http-client.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ - -#ifndef __MATRIX_HTTP_CLIENT_H__ -#define __MATRIX_HTTP_CLIENT_H__ - -#include -#include "matrix-glib.h" - -G_BEGIN_DECLS - -#define MATRIX_TYPE_HTTP_CLIENT (matrix_http_client_get_type()) -#define MATRIX_HTTP_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), MATRIX_TYPE_HTTP_CLIENT, MatrixHTTPClient)) -#define MATRIX_HTTP_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MATRIX_TYPE_HTTP_CLIENT, MatrixHTTPClientClass)) -#define MATRIX_IS_HTTP_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), MATRIX_TYPE_HTTP_CLIENT)) -#define MATRIX_IS_HTTP_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), MATRIX_TYPE_HTTP_CLIENT)) -#define MATRIX_HTTP_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), MATRIX_TYPE_HTTP_CLIENT, MatrixHTTPClientClass)) - -typedef struct _MatrixHTTPClient MatrixHTTPClient; -typedef struct _MatrixHTTPClientClass MatrixHTTPClientClass; - -struct _MatrixHTTPClient { - MatrixHTTPAPI parent_instance; -}; - -struct _MatrixHTTPClientClass { - MatrixHTTPAPIClass parent_class; -}; - -GType matrix_http_client_get_type(void) G_GNUC_CONST; - -MatrixClient *matrix_http_client_new(const gchar *base_url); - -G_END_DECLS - -#endif /* __MATRIX_HTTP_CLIENT_H__ */ diff --git a/src/matrix-http-client.vala b/src/matrix-http-client.vala new file mode 100644 index 0000000..84800b2 --- /dev/null +++ b/src/matrix-http-client.vala @@ -0,0 +1,137 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +/** + * An event-driven client class to communicate with HTTP based + * Matrix.org servers. + */ +public class Matrix.HTTPClient : Matrix.HTTPAPI, Matrix.Client { + private bool _polling = false; + private ulong _event_timeout = 30000; + + public + HTTPClient(string base_url) + { + Object(base_url : base_url); + } + + public void + login_with_password(string username, string password) + throws Matrix.Error + { + var builder = new Json.Builder(); + + builder.begin_object(); + + builder.set_member_name("user"); + builder.add_string_value(username); + + builder.set_member_name("password"); + builder.add_string_value(password); + + builder.end_object(); + + login((i, content_type, json_content, raw_content, error) => { + login_finished((error == null) || (error is Matrix.Error.NONE)); + } + ,"m.login.password", + builder.get_root()); + } + + public void + register_with_password(string? username, string password) + throws Matrix.Error + { + register_account( + (i, content_type, json_content, raw_content, error) => { + login_finished((error is Matrix.Error.NONE)); + }, + Matrix.AccountKind.USER, + false, username, password); + } + + public void + logout() + throws Matrix.Error + { + token = null; + refresh_token = null; + abort_pending(); + } + + private void + cb_event_stream(string content_type, + Json.Node? json_content, + ByteArray? raw_content, + Matrix.Error? error) + { + string? end_token = null; + + if (error == null) { + var root_obj = json_content.get_object(); + Json.Node? node; + + if ((node = root_obj.get_member("chunk")) != null) { + var chunks = node.get_array(); + + chunks.foreach_element((ary, idx, member_node) => {}); + } + + if ((node = root_obj.get_member("end")) != null) { + end_token = node.get_string(); + } + } + + // Only continue polling if polling is still enabled, and + // there was no communication error during the last call + + if (_polling && ((error == null) || (error.code <= 500))) { + _polling = false; + + try { + event_stream( + (API.Callback)cb_event_stream, + end_token, + _event_timeout); + } catch (Matrix.Error e) {} + } + } + + public void + begin_polling() + throws Matrix.Error + { + try { + event_stream((API.Callback)cb_event_stream, null, _event_timeout); + _polling = true; + } catch (Matrix.Error e) { + throw e; + } + } + + public void + stop_polling(bool cancel_ongoing) + throws Matrix.Error + { + _polling = false; + + if (cancel_ongoing) { + abort_pending(); + } + } +}