Rework MatrixHTTPClient in Vala
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -65,3 +65,4 @@ Makefile.in | ||||
| /src/matrix-client.c | ||||
| /src/matrix-enums.c | ||||
| /src/matrix-http-api.c | ||||
| /src/matrix-http-client.c | ||||
|   | ||||
| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|  * <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #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); | ||||
| } | ||||
| @@ -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 | ||||
|  * <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __MATRIX_HTTP_CLIENT_H__ | ||||
| #define __MATRIX_HTTP_CLIENT_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #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__ */ | ||||
							
								
								
									
										137
									
								
								src/matrix-http-client.vala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/matrix-http-client.vala
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  * <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * 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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user