From 32514005914a78afaae3a385d02c6f44ab466b47 Mon Sep 17 00:00:00 2001 From: Kostas Date: Wed, 19 Jan 2022 14:41:30 +0200 Subject: [PATCH 01/18] mgclient wasm poc draft --- CMakeLists.txt | 15 +- README.md | 14 ++ include/mgclient.h | 469 ++++++++++++++++++++++++------------------- src/CMakeLists.txt | 60 +++--- src/linux/mgsocket.c | 28 ++- src/mgclient.c | 31 ++- src/mgsession.c | 8 + src/mgtransport.c | 4 + 8 files changed, 386 insertions(+), 243 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 506f82e..f6e743e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,10 @@ set(mgclient_SOVERSION 2) add_definitions(-DMGCLIENT_VERSION="${mgclient_VERSION}") # Deal with the operating system. +if((NOT UNIX) AND EMSCRIPTEN) + message(FATAL_ERROR "WASM build is only supported in Linux") +endif() + if(WIN32) message(STATUS "ON WINDOWS BUILD") set(MGCLIENT_ON_WINDOWS TRUE) @@ -29,14 +33,17 @@ if(WIN32) # "lib;" breaks gtest lib referencing. set(MGCLIENT_FIND_LIBRARY_PREFIXES "lib") elseif(UNIX AND NOT APPLE) - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "Unsupported operating system. Please create issue or contribute!") + endif() + if(EMSCRIPTEN) + message(STATUS "ON LINUX WASM BUILD") + else() message(STATUS "ON LINUX BUILD") + endif() set(MGCLIENT_ON_LINUX TRUE) add_definitions(-DMGCLIENT_ON_LINUX) set(MGCLIENT_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") - else() - message(FATAL_ERROR "Unsupported operating system. Please create issue or contribute!") - endif() elseif(APPLE) message(STATUS "ON APPLE BUILD") set(MGCLIENT_ON_APPLE TRUE) diff --git a/README.md b/README.md index 80b3c62..b88717a 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,20 @@ cd build cmake .. -G "MinGW Makefiles" cmake --build . --target install ``` +## Building WASM (linux only) +Compiling `mgclient` requires the Emscripten sdk found in https://github.com/emscripten-core/emsdk and OpenSSL WASM. + - Clone the emsdk repo above and do `./emsdk install latest && ./emsdk activate latest && source ./emsdk_env.sh` + - Clone openssl repo found in https://github.com/openssl/openssl and compile it to WASM with `emconfigure ./Configure -no-asm -no-tests && make -j8` + - Create a build directory under, i.e., `mgclient/build` and then do (replace `PATH_TO` to the right path): + ``` + emcmake cmake .. -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=PATH_TO/openssl/apps/ -DOPENSSL_INCLUDE_DIR=PATH_TO/openssl/include/ -DOPENSSL_SSL_LIBRARY=PATH_TO/openssl/libssl.a -DOPENSSL_CRYPTO_LIBRARY=PATH_TO/openssl/libcrypto.a + + emmake make + + emcc src/libmgclient.a -o mgclient.js -s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME="load_mgclient" --shared-memory --no-entry -s USE_PTHREADS=1 -s SOCKET_DEBUG=1 -s WEBSOCKET_SUBPROTOCOL="binary" -s EXPORTED_FUNCTIONS='_mg_init, _mg_finalize, _mg_session_params_make, _mg_session_params_destroy, _mg_session_params_set_host, _mg_session_params_set_port, _mg_session_params_set_sslmode, _mg_session_error, _mg_session_run, _mg_session_fetch, _mg_session_pull, _mg_connect' -s EXPORTED_RUNTIME_METHODS="ccall,cwrap,getValue,setValue" -L/home/rim/Desktop/openssl/ -lssl -lcrypto + + ``` +Now there should be an `mgclient.js` and an `mgclient.wasm` found in `mgclient/build/` ## Using the library diff --git a/include/mgclient.h b/include/mgclient.h index 20c6fdc..7f7082e 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -17,6 +17,12 @@ #include "mgclient-export.h" +#ifdef __EMSCRIPTEN__ +#include "emscripten.h" +#else +#define EMSCRIPTEN_KEEPALIVE +#endif + #ifdef __cplusplus extern "C" { #endif @@ -132,17 +138,17 @@ extern "C" { /// Client software version. /// /// \return Client version in the major.minor.patch format. -MGCLIENT_EXPORT const char *mg_client_version(); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_client_version(); /// Initializes the client (the whole process). /// Should be called at the beginning of each process using the client. /// /// \return Zero if initialization was successful. -MGCLIENT_EXPORT int mg_init(); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_init(); /// Finalizes the client (the whole process). /// Should be called at the end of each process using the client. -MGCLIENT_EXPORT void mg_finalize(); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_finalize(); /// An enum listing all the types as specified by Bolt protocol. enum mg_value_type { @@ -292,24 +298,25 @@ typedef struct mg_point_3d mg_point_3d; /// Constructs a nil \ref mg_value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_null(); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_null(); /// Constructs a boolean \ref mg_value. /// /// \param val If the parameter is zero, constructed value will be false. /// Otherwise, it will be true. /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_bool(int val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_bool(int val); /// Constructs an integer \ref mg_value with the given underlying value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_integer(int64_t val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_integer( + int64_t val); /// Constructs a float \ref mg_value with the given underlying value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_float(double val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_float(double val); /// Constructs a string \ref mg_value given a null-terminated string. /// @@ -319,225 +326,253 @@ MGCLIENT_EXPORT mg_value *mg_value_make_float(double val); /// \param str A null-terminated UTF-8 string. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_string(const char *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_string( + const char *str); /// Construct a string \ref mg_value given the underlying \ref mg_string. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_string2(mg_string *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_string2( + mg_string *str); /// Constructs a list \ref mg_value given the underlying \ref mg_list. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_list(mg_list *list); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_list( + mg_list *list); /// Constructs a map \ref mg_value given the underlying \ref mg_map. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_map(mg_map *map); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_map(mg_map *map); /// Constructs a node \ref mg_value given the underlying \ref mg_node. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_node(mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_node( + mg_node *node); /// Constructs a relationship \ref mg_value given the underlying /// \ref mg_relationship. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_relationship(mg_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_relationship( + mg_relationship *rel); /// Constructs an unbound relationship \ref mg_value given the underlying /// \ref mg_unbound_relationship. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_unbound_relationship( - mg_unbound_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value * +mg_value_make_unbound_relationship(mg_unbound_relationship *rel); /// Constructs a path \ref mg_value given the underlying \ref mg_path. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_path(mg_path *path); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_path( + mg_path *path); /// Constructs a date \ref mg_value given the underlying \ref mg_date. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_date(mg_date *date); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date( + mg_date *date); /// Constructs a time \ref mg_value given the underlying \ref mg_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_time(mg_time *time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_time( + mg_time *time); /// Constructs a local time \ref mg_value given the underlying \ref /// mg_local_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_local_time(mg_local_time *local_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_local_time( + mg_local_time *local_time); /// Constructs a date and time \ref mg_value given the underlying \ref /// mg_date_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_date_time(mg_date_time *date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date_time( + mg_date_time *date_time); /// Constructs a date and time \ref mg_value given the underlying \ref /// mg_date_time_zone_id. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_date_time_zone_id( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date_time_zone_id( mg_date_time_zone_id *date_time_zone_id); /// Constructs a local date and time \ref mg_value given the underlying \ref /// mg_local_date_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_local_date_time( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_local_date_time( mg_local_date_time *local_date_time); /// Constructs a duration \ref mg_value given the underlying \ref mg_duration. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_duration(mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_duration( + mg_duration *duration); /// Constructs a 2D point \ref mg_value given the underlying \ref mg_point_2d. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_point_2d(mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_point_2d( + mg_point_2d *point_2d); /// Constructs a 3D point \ref mg_value given the underlying \ref mg_point_3d. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_make_point_3d(mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_point_3d( + mg_point_3d *point_3d); /// Returns the type of the given \ref mg_value. -MGCLIENT_EXPORT enum mg_value_type mg_value_get_type(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_value_type mg_value_get_type( + const mg_value *val); /// Returns non-zero value if value contains true, zero otherwise. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT int mg_value_bool(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_value_bool(const mg_value *val); /// Returns the underlying integer value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT int64_t mg_value_integer(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_value_integer(const mg_value *val); /// Returns the underlying float value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT double mg_value_float(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_value_float(const mg_value *val); /// Returns the underlying \ref mg_string value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_string *mg_value_string(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_value_string( + const mg_value *val); /// Returns the underlying \ref mg_list value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_list *mg_value_list(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_value_list( + const mg_value *val); /// Returns the underlying \ref mg_map value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_map *mg_value_map(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_value_map( + const mg_value *val); /// Returns the underlying \ref mg_node value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_node *mg_value_node(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_node *mg_value_node( + const mg_value *val); /// Returns the underlying \ref mg_relationship value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_relationship *mg_value_relationship( - const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_relationship * +mg_value_relationship(const mg_value *val); /// Returns the underlying \ref mg_unbound_relationship value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_unbound_relationship *mg_value_unbound_relationship( - const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_unbound_relationship * +mg_value_unbound_relationship(const mg_value *val); /// Returns the underlying \ref mg_path value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_path *mg_value_path(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_path *mg_value_path( + const mg_value *val); /// Returns the underlying \ref mg_date value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_date *mg_value_date(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date *mg_value_date( + const mg_value *val); /// Returns the underlying \ref mg_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_time *mg_value_time(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_time *mg_value_time( + const mg_value *val); /// Returns the underlying \ref mg_local_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_local_time *mg_value_local_time(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_local_time *mg_value_local_time( + const mg_value *val); /// Returns the underlying \ref mg_date_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_date_time *mg_value_date_time(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date_time *mg_value_date_time( + const mg_value *val); /// Returns the underlying \ref mg_date_time_zone_id value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_date_time_zone_id *mg_value_date_time_zone_id( - const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date_time_zone_id * +mg_value_date_time_zone_id(const mg_value *val); /// Returns the underlying \ref mg_local_date_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_local_date_time *mg_value_local_date_time( - const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_local_date_time * +mg_value_local_date_time(const mg_value *val); /// Returns the underlying \ref mg_duration value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_duration *mg_value_duration(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_duration *mg_value_duration( + const mg_value *val); /// Returns the underlying \ref mg_point_2d value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_point_2d *mg_value_point_2d(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_point_2d *mg_value_point_2d( + const mg_value *val); /// Returns the underlying \ref mg_point_3d value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT const mg_point_3d *mg_value_point_3d(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_point_3d *mg_value_point_3d( + const mg_value *val); /// Creates a copy of the given value. /// /// \return Pointer to the copy or NULL if error occurred. -MGCLIENT_EXPORT mg_value *mg_value_copy(const mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_copy( + const mg_value *val); /// Destroys the given value. -MGCLIENT_EXPORT void mg_value_destroy(mg_value *val); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_value_destroy(mg_value *val); /// Constructs a string given a null-terminated string. /// @@ -548,7 +583,7 @@ MGCLIENT_EXPORT void mg_value_destroy(mg_value *val); /// /// \return A pointer to the newly constructed `mg_string` object or \c NULL /// if an error occurred. -MGCLIENT_EXPORT mg_string *mg_string_make(const char *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_make(const char *str); /// Constructs a string given its length (in bytes) and contents. /// @@ -559,21 +594,25 @@ MGCLIENT_EXPORT mg_string *mg_string_make(const char *str); /// /// \return A pointer to the newly constructed `mg_string` object or \c NULL /// if an error occurred. -MGCLIENT_EXPORT mg_string *mg_string_make2(uint32_t len, const char *data); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_make2( + uint32_t len, const char *data); /// Returns a pointer to the beginning of data buffer of string \p str. -MGCLIENT_EXPORT const char *mg_string_data(const mg_string *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_string_data( + const mg_string *str); /// Returns the length (in bytes) of string \p str. -MGCLIENT_EXPORT uint32_t mg_string_size(const mg_string *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t +mg_string_size(const mg_string *str); /// Creates a copy of the given string. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_string *mg_string_copy(const mg_string *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_copy( + const mg_string *str); /// Destroys the given string. -MGCLIENT_EXPORT void mg_string_destroy(mg_string *str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_string_destroy(mg_string *str); /// Constructs a list that can hold at most \p capacity elements. /// @@ -584,7 +623,8 @@ MGCLIENT_EXPORT void mg_string_destroy(mg_string *str); /// /// \return A pointer to the newly constructed empty list or NULL if an error /// occurred. -MGCLIENT_EXPORT mg_list *mg_list_make_empty(uint32_t capacity); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_list *mg_list_make_empty( + uint32_t capacity); /// Appends an element at the end of the list \p list. /// @@ -596,24 +636,26 @@ MGCLIENT_EXPORT mg_list *mg_list_make_empty(uint32_t capacity); /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT int mg_list_append(mg_list *list, mg_value *value); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_list_append(mg_list *list, + mg_value *value); /// Returns the number of elements in list \p list. -MGCLIENT_EXPORT uint32_t mg_list_size(const mg_list *list); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t mg_list_size(const mg_list *list); /// Retrieves the element at position \p pos in list \p list. /// /// \return A pointer to required list element. If \p pos is outside of list /// bounds, \c NULL is returned. -MGCLIENT_EXPORT const mg_value *mg_list_at(const mg_list *list, uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_list_at( + const mg_list *list, uint32_t pos); /// Creates a copy of the given list. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_list *mg_list_copy(const mg_list *list); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_list *mg_list_copy(const mg_list *list); /// Destroys the given list. -MGCLIENT_EXPORT void mg_list_destroy(mg_list *list); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_list_destroy(mg_list *list); /// Constructs an empty map that can hold at most \p capacity key-value pairs. /// @@ -625,7 +667,8 @@ MGCLIENT_EXPORT void mg_list_destroy(mg_list *list); /// /// \return A pointer to the newly constructed empty map or NULL if an error /// occurred. -MGCLIENT_EXPORT mg_map *mg_map_make_empty(uint32_t capacity); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_map *mg_map_make_empty( + uint32_t capacity); /// Inserts the given key-value pair into the map. /// @@ -646,8 +689,9 @@ MGCLIENT_EXPORT mg_map *mg_map_make_empty(uint32_t capacity); /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT int mg_map_insert(mg_map *map, const char *key_str, - mg_value *value); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert(mg_map *map, + const char *key_str, + mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -667,8 +711,9 @@ MGCLIENT_EXPORT int mg_map_insert(mg_map *map, const char *key_str, /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT int mg_map_insert2(mg_map *map, mg_string *key, - mg_value *value); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert2(mg_map *map, + mg_string *key, + mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -688,8 +733,8 @@ MGCLIENT_EXPORT int mg_map_insert2(mg_map *map, mg_string *key, /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT int mg_map_insert_unsafe(mg_map *map, const char *key_str, - mg_value *value); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe( + mg_map *map, const char *key_str, mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -707,8 +752,9 @@ MGCLIENT_EXPORT int mg_map_insert_unsafe(mg_map *map, const char *key_str, /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT int mg_map_insert_unsafe2(mg_map *map, mg_string *key, - mg_value *value); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe2(mg_map *map, + mg_string *key, + mg_value *value); /// Looks up a map value with the given key. /// @@ -718,8 +764,8 @@ MGCLIENT_EXPORT int mg_map_insert_unsafe2(mg_map *map, mg_string *key, /// /// \return If the key is found in the map, the pointer to the corresponding /// \ref mg_value is returned. Otherwise, \c NULL is returned. -MGCLIENT_EXPORT const mg_value *mg_map_at(const mg_map *map, - const char *key_str); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_at( + const mg_map *map, const char *key_str); /// Looks up a map value with the given key. /// @@ -730,106 +776,115 @@ MGCLIENT_EXPORT const mg_value *mg_map_at(const mg_map *map, /// /// \return If the key is found in the map, the pointer to the corresponding /// \ref mg_value is returned. Otherwise, \c NULL is returned. -MGCLIENT_EXPORT const mg_value *mg_map_at2(const mg_map *map, uint32_t key_size, - const char *key_data); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_at2( + const mg_map *map, uint32_t key_size, const char *key_data); /// Returns the number of key-value pairs in map \p map. -MGCLIENT_EXPORT uint32_t mg_map_size(const mg_map *map); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t mg_map_size(const mg_map *map); /// Retrieves the key at position \p pos in map \p map. /// /// \return A pointer to required key. If \p pos is outside of map bounds, \c /// NULL is returned. -MGCLIENT_EXPORT const mg_string *mg_map_key_at(const mg_map *, uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_map_key_at( + const mg_map *, uint32_t pos); /// Retrieves the value at position \p pos in map \p map. /// /// \return A pointer to required value. If \p pos is outside of map bounds, /// \c NULL is returned. -MGCLIENT_EXPORT const mg_value *mg_map_value_at(const mg_map *, uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_value_at( + const mg_map *, uint32_t pos); /// Creates a copy of the given map. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_map *mg_map_copy(const mg_map *map); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_map *mg_map_copy(const mg_map *map); /// Destroys the given map. -MGCLIENT_EXPORT void mg_map_destroy(mg_map *map); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_map_destroy(mg_map *map); /// Returns the ID of node \p node. -MGCLIENT_EXPORT int64_t mg_node_id(const mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_node_id(const mg_node *node); /// Returns the number of labels of node \p node. -MGCLIENT_EXPORT uint32_t mg_node_label_count(const mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t +mg_node_label_count(const mg_node *node); /// Returns the label at position \p pos in node \p node's label list. /// /// \return A pointer to the required label. If \p pos is outside of label list /// bounds, \c NULL is returned. -MGCLIENT_EXPORT const mg_string *mg_node_label_at(const mg_node *node, - uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_node_label_at( + const mg_node *node, uint32_t pos); /// Returns property map of node \p node. -MGCLIENT_EXPORT const mg_map *mg_node_properties(const mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_node_properties( + const mg_node *node); /// Creates a copy of the given node. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_node *mg_node_copy(const mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_node *mg_node_copy(const mg_node *node); /// Destroys the given node. -MGCLIENT_EXPORT void mg_node_destroy(mg_node *node); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_node_destroy(mg_node *node); /// Returns the ID of the relationship \p rel. -MGCLIENT_EXPORT int64_t mg_relationship_id(const mg_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_relationship_id(const mg_relationship *rel); /// Returns the ID of the start node of relationship \p rel. -MGCLIENT_EXPORT int64_t mg_relationship_start_id(const mg_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_relationship_start_id(const mg_relationship *rel); /// Returns the ID of the end node of relationship \p rel. -MGCLIENT_EXPORT int64_t mg_relationship_end_id(const mg_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_relationship_end_id(const mg_relationship *rel); /// Returns the type of the relationship \p rel. -MGCLIENT_EXPORT const mg_string *mg_relationship_type( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_relationship_type( const mg_relationship *rel); /// Returns the property map of the relationship \p rel. -MGCLIENT_EXPORT const mg_map *mg_relationship_properties( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_relationship_properties( const mg_relationship *rel); /// Creates a copy of the given relationship. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_relationship *mg_relationship_copy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_relationship *mg_relationship_copy( const mg_relationship *rel); /// Destroys the given relationship. -MGCLIENT_EXPORT void mg_relationship_destroy(mg_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_relationship_destroy( + mg_relationship *rel); /// Returns the ID of the unbound relationship \p rel. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_unbound_relationship_id(const mg_unbound_relationship *rel); /// Returns the type of the unbound relationship \p rel. -MGCLIENT_EXPORT const mg_string *mg_unbound_relationship_type( - const mg_unbound_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string * +mg_unbound_relationship_type(const mg_unbound_relationship *rel); /// Returns the property map of the unbound relationship \p rel. -MGCLIENT_EXPORT const mg_map *mg_unbound_relationship_properties( - const mg_unbound_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map * +mg_unbound_relationship_properties(const mg_unbound_relationship *rel); /// Creates a copy of the given unbound relationship. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_unbound_relationship *mg_unbound_relationship_copy( - const mg_unbound_relationship *rel); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_unbound_relationship * +mg_unbound_relationship_copy(const mg_unbound_relationship *rel); /// Destroys the given unbound relationship. -MGCLIENT_EXPORT void mg_unbound_relationship_destroy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_unbound_relationship_destroy( mg_unbound_relationship *rel); /// Returns the length (the number of edges) of path \p path. -MGCLIENT_EXPORT uint32_t mg_path_length(const mg_path *path); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t +mg_path_length(const mg_path *path); /// Returns the node at position \p pos in the traversal of path \p path. /// @@ -837,8 +892,8 @@ MGCLIENT_EXPORT uint32_t mg_path_length(const mg_path *path); /// /// \return A pointer to the required node. If \p pos is out of path bounds, \c /// NULL is returned. -MGCLIENT_EXPORT const mg_node *mg_path_node_at(const mg_path *path, - uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_node *mg_path_node_at( + const mg_path *path, uint32_t pos); /// Returns the relationship at position \p pos in traversal of path \p path. /// @@ -846,8 +901,8 @@ MGCLIENT_EXPORT const mg_node *mg_path_node_at(const mg_path *path, /// /// \return A pointer to the required relationship. If \p pos is outside of /// path bounds, \c NULL is returned. -MGCLIENT_EXPORT const mg_unbound_relationship *mg_path_relationship_at( - const mg_path *path, uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_unbound_relationship * +mg_path_relationship_at(const mg_path *path, uint32_t pos); /// Checks if the relationship at position \p pos in traversal of path \p path /// is reversed. @@ -858,189 +913,197 @@ MGCLIENT_EXPORT const mg_unbound_relationship *mg_path_relationship_at( /// underlying relationship in the data graph, and 1 if it is traversed /// in the opposite direction. If \p pos is outside of path bounds, -1 /// is returned. -MGCLIENT_EXPORT int mg_path_relationship_reversed_at(const mg_path *path, - uint32_t pos); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_path_relationship_reversed_at( + const mg_path *path, uint32_t pos); /// Creates a copy of the given path. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT mg_path *mg_path_copy(const mg_path *path); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_path *mg_path_copy(const mg_path *path); /// Destroys the given path. -MGCLIENT_EXPORT void mg_path_destroy(mg_path *path); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_path_destroy(mg_path *path); /// Creates mg_date from days. /// \return a pointer to mg_date or NULL if an error occurred. -MGCLIENT_EXPORT mg_date *mg_date_make(int64_t days); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date *mg_date_make(int64_t days); /// Returns days since the Unix epoch. -MGCLIENT_EXPORT int64_t mg_date_days(const mg_date *date); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_days(const mg_date *date); /// Creates a copy of the given date. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_date *mg_date_copy(const mg_date *date); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date *mg_date_copy(const mg_date *date); /// Destroys the given date. -MGCLIENT_EXPORT void mg_date_destroy(mg_date *date); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_destroy(mg_date *date); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT int64_t mg_time_nanoseconds(const mg_time *time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_time_nanoseconds(const mg_time *time); /// Returns time zone offset in seconds from UTC. -MGCLIENT_EXPORT int64_t mg_time_tz_offset_seconds(const mg_time *time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_time_tz_offset_seconds(const mg_time *time); /// Creates a copy of the given time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_time *mg_time_copy(const mg_time *time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_time *mg_time_copy(const mg_time *time); /// Destroys the given time. -MGCLIENT_EXPORT void mg_time_destroy(mg_time *time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_time_destroy(mg_time *time); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_local_time_nanoseconds(const mg_local_time *local_time); /// Creates mg_local_time from nanoseconds. /// \return a pointer to mg_local_time or NULL if an error occurred. -MGCLIENT_EXPORT mg_local_time *mg_local_time_make(int64_t nanoseconds); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_time *mg_local_time_make( + int64_t nanoseconds); /// Creates a copy of the given local time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_local_time *mg_local_time_copy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_time *mg_local_time_copy( const mg_local_time *local_time); /// Destroys the given local time. -MGCLIENT_EXPORT void mg_local_time_destroy(mg_local_time *local_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_time_destroy( + mg_local_time *local_time); /// Returns seconds since Unix epoch. -MGCLIENT_EXPORT int64_t mg_date_time_seconds(const mg_date_time *date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_date_time_seconds(const mg_date_time *date_time); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT int64_t mg_date_time_nanoseconds(const mg_date_time *date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_date_time_nanoseconds(const mg_date_time *date_time); /// Returns time zone offset in minutes from UTC. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_time_tz_offset_minutes(const mg_date_time *date_time); /// Creates a copy of the given date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_date_time *mg_date_time_copy(const mg_date_time *date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time *mg_date_time_copy( + const mg_date_time *date_time); /// Destroys the given date and time. -MGCLIENT_EXPORT void mg_date_time_destroy(mg_date_time *date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_destroy( + mg_date_time *date_time); /// Returns seconds since Unix epoch. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_time_zone_id_seconds(const mg_date_time_zone_id *date_time_zone_id); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_time_zone_id_nanoseconds(const mg_date_time_zone_id *date_time_zone_id); /// Returns time zone represented by the identifier. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_time_zone_id_tz_id(const mg_date_time_zone_id *date_time_zone_id); /// Creates a copy of the given date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_date_time_zone_id *mg_date_time_zone_id_copy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time_zone_id *mg_date_time_zone_id_copy( const mg_date_time_zone_id *date_time_zone_id); /// Destroys the given date and time. -MGCLIENT_EXPORT void mg_date_time_zone_id_destroy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_zone_id_destroy( mg_date_time_zone_id *date_time_zone_id); /// Creates mg_local_date_time from seconds and nanoseconds. /// \return a pointer to mg_local_date_time or NULL if an error occurred. -MGCLIENT_EXPORT mg_local_date_time *mg_local_date_time_make( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time *mg_local_date_time_make( int64_t seconds, int64_t nanoseconds); // /// Returns seconds since Unix epoch. This includes the hours, minutes, seconds /// fields of the local_time. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_local_date_time_seconds(const mg_local_date_time *local_date_time); /// Returns subseconds of the local_time field as nanoseconds. -MGCLIENT_EXPORT int64_t +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_local_date_time_nanoseconds(const mg_local_date_time *local_date_time); /// Creates a copy of the given local date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_local_date_time *mg_local_date_time_copy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time *mg_local_date_time_copy( const mg_local_date_time *local_date_time); /// Destroy the given local date and time. -MGCLIENT_EXPORT void mg_local_date_time_destroy( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_date_time_destroy( mg_local_date_time *local_date_time); /// Creates mg_duration from months, days, seconds and nanoseconds. /// \return a pointer to mg_duration or NULL if an error occurred. -MGCLIENT_EXPORT mg_duration *mg_duration_make(int64_t months, int64_t days, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_make(int64_t months, int64_t days, int64_t seconds, int64_t nanoseconds); /// Returns the months part of the temporal amount. -MGCLIENT_EXPORT int64_t mg_duration_months(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_months(const mg_duration *duration); /// Returns the days part of the temporal amount. -MGCLIENT_EXPORT int64_t mg_duration_days(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_days(const mg_duration *duration); /// Returns the seconds part of the temporal amount. -MGCLIENT_EXPORT int64_t mg_duration_seconds(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_seconds(const mg_duration *duration); /// Returns the nanoseconds part of the temporal amount. -MGCLIENT_EXPORT int64_t mg_duration_nanoseconds(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_nanoseconds(const mg_duration *duration); /// Creates a copy of the given duration. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_duration *mg_duration_copy(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_copy(const mg_duration *duration); /// Destroy the given duration. -MGCLIENT_EXPORT void mg_duration_destroy(mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_duration_destroy(mg_duration *duration); /// Returns SRID of the 2D point. -MGCLIENT_EXPORT int64_t mg_point_2d_srid(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_point_2d_srid(const mg_point_2d *point_2d); /// Returns the x coordinate of the 2D point. -MGCLIENT_EXPORT double mg_point_2d_x(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_x(const mg_point_2d *point_2d); /// Returns the y coordinate of the 2D point. -MGCLIENT_EXPORT double mg_point_2d_y(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_y(const mg_point_2d *point_2d); /// Creates a copy of the given 2D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d); /// Destroys the given 2D point. -MGCLIENT_EXPORT void mg_point_2d_destroy(mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_2d_destroy(mg_point_2d *point_2d); /// Returns SRID of the 3D point. -MGCLIENT_EXPORT int64_t mg_point_3d_srid(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_point_3d_srid(const mg_point_3d *point_3d); /// Returns the x coordinate of the 3D point. -MGCLIENT_EXPORT double mg_point_3d_x(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_x(const mg_point_3d *point_3d); /// Returns the y coordinate of the 3D point. -MGCLIENT_EXPORT double mg_point_3d_y(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_y(const mg_point_3d *point_3d); /// Returns the z coordinate of the 3D point. -MGCLIENT_EXPORT double mg_point_3d_z(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_z(const mg_point_3d *point_3d); /// Creates a copy of the given 3D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d); /// Destroys the given 3D point. -MGCLIENT_EXPORT void mg_point_3d_destroy(mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_3d_destroy(mg_point_3d *point_3d); /// Marks a \ref mg_session ready to execute a new query using \ref /// mg_session_run. @@ -1214,55 +1277,57 @@ typedef int (*mg_trust_callback_type)(const char *, const char *, const char *, const char *, void *); /// Creates a new `mg_session_params` object. -MGCLIENT_EXPORT mg_session_params *mg_session_params_make(); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_session_params * +mg_session_params_make(); /// Destroys a `mg_session_params` object. -MGCLIENT_EXPORT void mg_session_params_destroy(mg_session_params *); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_destroy( + mg_session_params *); /// Getters and setters for `mg_session_params` values. -MGCLIENT_EXPORT void mg_session_params_set_address(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_address(mg_session_params *, const char *address); -MGCLIENT_EXPORT void mg_session_params_set_host(mg_session_params *, - const char *host); -MGCLIENT_EXPORT void mg_session_params_set_port(mg_session_params *, - uint16_t port); -MGCLIENT_EXPORT void mg_session_params_set_username(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_host( + mg_session_params *, const char *host); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_port( + mg_session_params *, uint16_t port); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_username(mg_session_params *, const char *username); -MGCLIENT_EXPORT void mg_session_params_set_password(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_password(mg_session_params *, const char *password); -MGCLIENT_EXPORT void mg_session_params_set_user_agent(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_user_agent(mg_session_params *, const char *user_agent); -MGCLIENT_EXPORT void mg_session_params_set_sslmode(mg_session_params *, - enum mg_sslmode sslmode); -MGCLIENT_EXPORT void mg_session_params_set_sslcert(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslmode( + mg_session_params *, enum mg_sslmode sslmode); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslcert(mg_session_params *, const char *sslcert); -MGCLIENT_EXPORT void mg_session_params_set_sslkey(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslkey(mg_session_params *, const char *sslkey); -MGCLIENT_EXPORT void mg_session_params_set_trust_callback( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_callback( mg_session_params *, mg_trust_callback_type trust_callback); -MGCLIENT_EXPORT void mg_session_params_set_trust_data(mg_session_params *, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_data(mg_session_params *, void *trust_data); -MGCLIENT_EXPORT const char *mg_session_params_get_address( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_address( const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_host( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_host( const mg_session_params *); -MGCLIENT_EXPORT uint16_t mg_session_params_get_port(const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_username( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint16_t mg_session_params_get_port(const mg_session_params *); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_username( const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_password( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_password( const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_user_agent( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_user_agent( const mg_session_params *); -MGCLIENT_EXPORT enum mg_sslmode mg_session_params_get_sslmode( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_sslmode mg_session_params_get_sslmode( const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_sslcert( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslcert( const mg_session_params *); -MGCLIENT_EXPORT const char *mg_session_params_get_sslkey( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslkey( const mg_session_params *); -MGCLIENT_EXPORT mg_trust_callback_type +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_trust_callback_type mg_session_params_get_trust_callback(const mg_session_params *params); -MGCLIENT_EXPORT void *mg_session_params_get_trust_data( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void *mg_session_params_get_trust_data( const mg_session_params *); /// Makes a new connection to the database server. @@ -1279,20 +1344,22 @@ MGCLIENT_EXPORT void *mg_session_params_get_trust_data( /// \return Returns 0 if connected successfuly, otherwise returns a non-zero /// error code. A more detailed error message can be obtained by using /// \ref mg_session_error on \p session, unless it is set to NULL. -MGCLIENT_EXPORT int mg_connect(const mg_session_params *params, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_connect(const mg_session_params *params, mg_session **session); /// Returns the status of \ref mg_session. /// /// \return One of \ref MG_SESSION_READY, \ref MG_SESSION_EXECUTING, /// \ref MG_SESSION_BAD. -MGCLIENT_EXPORT int mg_session_status(const mg_session *session); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_status( + const mg_session *session); /// Obtains the error message stored in \ref mg_session (if any). -MGCLIENT_EXPORT const char *mg_session_error(mg_session *session); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_error( + mg_session *session); /// Destroys a \ref mg_session and releases all of its resources. -MGCLIENT_EXPORT void mg_session_destroy(mg_session *session); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_destroy(mg_session *session); /// An object encapsulating a single result row or query execution summary. Its /// lifetime is limited by lifetime of parent \ref mg_session. Also, invoking @@ -1340,10 +1407,9 @@ typedef struct mg_result mg_result; /// if an Explicit transaction was started. /// \return Returns 0 if query was submitted for execution successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT int mg_session_run(mg_session *session, const char *query, - const mg_map *params, - const mg_map *extra_run_information, - const mg_list **columns, int64_t *qid); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_run( + mg_session *session, const char *query, const mg_map *params, + const mg_map *extra_run_information, const mg_list **columns, int64_t *qid); /// Starts an Explicit transaction on the server. /// @@ -1372,7 +1438,7 @@ MGCLIENT_EXPORT int mg_session_run(mg_session *session, const char *query, /// database. /// \return Returns 0 if the transaction was started successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT int mg_session_begin_transaction( +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_begin_transaction( mg_session *session, const mg_map *extra_run_information); /// Commits current Explicit transaction. @@ -1383,7 +1449,7 @@ MGCLIENT_EXPORT int mg_session_begin_transaction( /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT int mg_session_commit_transaction(mg_session *session, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction(mg_session *session, mg_result **result); /// Rollbacks current Explicit transaction. @@ -1394,7 +1460,7 @@ MGCLIENT_EXPORT int mg_session_commit_transaction(mg_session *session, /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT int mg_session_rollback_transaction(mg_session *session, +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_rollback_transaction(mg_session *session, mg_result **result); /// Tries to fetch the next query result from \ref mg_session. @@ -1408,7 +1474,8 @@ MGCLIENT_EXPORT int mg_session_rollback_transaction(mg_session *session, /// no more result rows and that the query execution summary was stored /// in \p result. Its contents may be accessed using \ref /// mg_result_summary. On failure, a non-zero exit code is returned. -MGCLIENT_EXPORT int mg_session_fetch(mg_session *session, mg_result **result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_fetch(mg_session *session, + mg_result **result); /// Tries to pull results of a statement. /// @@ -1425,17 +1492,17 @@ MGCLIENT_EXPORT int mg_session_fetch(mg_session *session, mg_result **result); /// is only for Explicit transactions. /// \return Returns 0 if the result was pulled successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT int mg_session_pull(mg_session *session, - const mg_map *pull_information); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_pull( + mg_session *session, const mg_map *pull_information); /// Returns names of columns output by the current query execution. -MGCLIENT_EXPORT const mg_list *mg_result_columns(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_columns(const mg_result *result); /// Returns column values of current result row. -MGCLIENT_EXPORT const mg_list *mg_result_row(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_row(const mg_result *result); /// Returns query execution summary. -MGCLIENT_EXPORT const mg_map *mg_result_summary(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_result_summary(const mg_result *result); #ifdef __cplusplus } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5723526..621bb1a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,8 @@ set(mgclient_src_files mgsession-decoder.c mgsession-encoder.c mgtransport.c - mgvalue.c) + mgvalue.c + mgwasm.c) if(MGCLIENT_ON_APPLE) list(APPEND mgclient_src_files apple/mgsocket.c) elseif(MGCLIENT_ON_LINUX) @@ -53,40 +54,49 @@ target_include_directories(mgclient-static target_link_libraries(mgclient-static PRIVATE ${OPENSSL_LIBRARIES} project_options project_c_warnings) + if(MGCLIENT_ON_WINDOWS) target_link_libraries(mgclient-static PUBLIC ws2_32) endif() -add_library(mgclient-shared SHARED ${mgclient_src_files}) -set_target_properties(mgclient-shared PROPERTIES - OUTPUT_NAME mgclient - SOVERSION ${mgclient_SOVERSION} - C_VISIBILITY_PRESET hidden) -target_include_directories(mgclient-shared - PRIVATE - "${PROJECT_SOURCE_DIR}/src" - PUBLIC - "${PROJECT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_BINARY_DIR}" - "${OPENSSL_INCLUDE_DIR}") -target_link_libraries(mgclient-shared PRIVATE ${OPENSSL_LIBRARIES}) +if(NOT EMSCRIPTEN) + generate_export_header(mgclient-shared + BASE_NAME "mgclient" + EXPORT_FILE_NAME "mgclient-export.h") + add_library(mgclient-shared STATIC ${mgclient_src_files}) + set_target_properties(mgclient-shared PROPERTIES + OUTPUT_NAME mgclient + SOVERSION ${mgclient_SOVERSION} + C_VISIBILITY_PRESET hidden) + target_include_directories(mgclient-shared + PRIVATE + "${PROJECT_SOURCE_DIR}/src" + PUBLIC + "${PROJECT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}" + "${OPENSSL_INCLUDE_DIR}") + target_link_libraries(mgclient-shared PRIVATE ${OPENSSL_LIBRARIES}) +endif() + if(MGCLIENT_ON_WINDOWS) target_link_libraries(mgclient-shared PUBLIC ws2_32) endif() -generate_export_header(mgclient-shared +generate_export_header(mgclient-static BASE_NAME "mgclient" EXPORT_FILE_NAME "mgclient-export.h") include(GNUInstallDirs) -install(TARGETS mgclient-static mgclient-shared - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(DIRECTORY - "${PROJECT_SOURCE_DIR}/include/" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/mgclient-export.h" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +if(NOT EMSCRIPTEN) + install(TARGETS mgclient-static mgclient-shared + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(DIRECTORY + "${PROJECT_SOURCE_DIR}/include/" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/mgclient-export.h" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index d2ae9a0..92d1a3d 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -17,13 +17,18 @@ #include "mgcommon.h" #include "mgsocket.h" -#define MG_RETRY_ON_EINTR(expression) \ - __extension__({ \ - long result; \ - do { \ - result = (long)(expression); \ - } while (result == -1L && errno == EINTR); \ - result; \ +#ifdef __EMSCRIPTEN__ +#include "emscripten.h" +#include "mgwasm.h" +#endif + +#define MG_RETRY_ON_EINTR(expression) \ + __extension__({ \ + long result; \ + do { \ + result = (long)(expression); \ + } while (result == -1L && (errno == EINTR)); \ + result; \ }) // Please refer to https://man7.org/linux/man-pages/man2 for more details about @@ -50,11 +55,18 @@ int mg_socket_create_handle_error(int sock, mg_session *session) { int mg_socket_connect(int sock, const struct sockaddr *addr, socklen_t addrlen) { long status = MG_RETRY_ON_EINTR(connect(sock, addr, addrlen)); - if (status == -1L) { + if (status == -1L && errno != EINPROGRESS) { return MG_ERROR_SOCKET; } +#ifdef __EMSCRIPTEN__ + if (yield_until_async_write(sock, 10) == -1) { + return MG_ERROR_SOCKET; + } +#endif + return MG_SUCCESS; } + int mg_socket_connect_handle_error(int *sock, int status, mg_session *session) { if (status != MG_SUCCESS) { mg_session_set_error(session, "couldn't connect to host: %s", diff --git a/src/mgclient.c b/src/mgclient.c index 7ce41a0..14bab43 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -28,9 +28,13 @@ #include "mgsocket.h" #include "mgvalue.h" +#ifdef __EMSCRIPTEN__ +#include "mgwasm.h" +#endif + const char *mg_client_version() { return MGCLIENT_VERSION; } -int mg_init() { return mg_socket_init(); } +int EMSCRIPTEN_KEEPALIVE mg_init() { return mg_socket_init(); } void mg_finalize() { mg_socket_finalize(); } @@ -204,6 +208,10 @@ static int mg_bolt_handshake(mg_session *session) { const uint32_t VERSION_NONE = htobe32(0); const uint32_t VERSION_1 = htobe32(1); const uint32_t VERSION_4_1 = htobe32(0x0104); +#ifdef __EMSCRIPTEN__ + int socket = ((mg_raw_transport *)session->transport)->sockfd; + yield_until_async_write(socket, 10); +#endif if (mg_transport_send(session->transport, MG_HANDSHAKE_MAGIC, strlen(MG_HANDSHAKE_MAGIC)) != 0 || mg_transport_send(session->transport, (char *)&VERSION_4_1, 4) != 0 || @@ -213,12 +221,15 @@ static int mg_bolt_handshake(mg_session *session) { mg_session_set_error(session, "failed to send handshake data"); return MG_ERROR_SEND_FAILED; } + uint32_t server_version; +#ifdef __EMSCRIPTEN__ + yield_until_async_read(socket, 10); +#endif if (mg_transport_recv(session->transport, (char *)&server_version, 4) != 0) { mg_session_set_error(session, "failed to receive handshake response"); return MG_ERROR_RECV_FAILED; } - if (server_version == VERSION_1) { session->version = 1; } else if (server_version == VERSION_4_1) { @@ -441,8 +452,15 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, abort(); } if (getaddrinfo_status != 0) { +#ifdef __EMSCRIPTEN__ + mg_session_set_error(session, "getaddrinfo failed: %s", + "Replace with error"); + // Not supported by emscripten: + // gai_strerror(getaddrinfo_status)); +#else mg_session_set_error(session, "getaddrinfo failed: %s", gai_strerror(getaddrinfo_status)); +#endif return MG_ERROR_NETWORK_FAILURE; } @@ -470,10 +488,12 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, return status; } +#ifndef __EMSCRIPTEN__ int set_options_status = mg_socket_options(tsockfd, session); if (set_options_status != MG_SUCCESS) { return set_options_status; } +#endif *sockfd = tsockfd; return 0; @@ -541,7 +561,6 @@ int mg_connect_ca(const mg_session_params *params, mg_session **session, if (status != 0) { goto cleanup; } - switch (params->sslmode) { case MG_SSLMODE_DISABLE: status = mg_raw_transport_init( @@ -587,12 +606,10 @@ int mg_connect_ca(const mg_session_params *params, mg_session **session, // mg_transport object took ownership of the socket. sockfd = -1; - status = mg_bolt_handshake(tsession); if (status != 0) { goto cleanup; } - status = mg_bolt_init(tsession, params); if (status != 0) { goto cleanup; @@ -688,6 +705,10 @@ int mg_session_run(mg_session *session, const char *query, const mg_map *params, goto fatal_failure; } +#ifdef __EMSCRIPTEN_ + int socket = ((mg_raw_transport *)session->transport)->sockfd; + yield_until_async_read(socket, 10); +#endif status = mg_session_receive_message(session); if (status != 0) { goto fatal_failure; diff --git a/src/mgsession.c b/src/mgsession.c index dc9fb8b..407830d 100644 --- a/src/mgsession.c +++ b/src/mgsession.c @@ -27,6 +27,7 @@ #include "mgcommon.h" #include "mgconstants.h" #include "mgsession.h" +#include "mgwasm.h" int mg_session_status(const mg_session *session) { if (!session) { @@ -227,6 +228,10 @@ int mg_session_ensure_space_for_chunk(mg_session *session, size_t chunk_size) { int mg_session_read_chunk(mg_session *session) { uint16_t chunk_size; +#ifdef __EMSCRIPTEN__ + int socket = ((mg_raw_transport *)session->transport)->sockfd; + yield_until_async_read(socket, 10); +#endif if (mg_transport_recv(session->transport, (char *)&chunk_size, 2) != 0) { mg_session_set_error(session, "failed to receive chunk size"); return MG_ERROR_RECV_FAILED; @@ -241,6 +246,9 @@ int mg_session_read_chunk(mg_session *session) { return status; } } +#ifdef __EMSCRIPTEN__ + yield_until_async_read(socket, 10); +#endif if (mg_transport_recv(session->transport, session->in_buffer + session->in_end, chunk_size) != 0) { diff --git a/src/mgtransport.c b/src/mgtransport.c index 7635c9f..672049c 100644 --- a/src/mgtransport.c +++ b/src/mgtransport.c @@ -19,7 +19,9 @@ #include #include #ifdef MGCLIENT_ON_LINUX +#ifndef _EMSCRIPTEN_ #include +#endif #endif // MGCLIENT_ON_LINUX #include "mgallocator.h" @@ -119,6 +121,7 @@ static char *hex_encode(unsigned char *data, unsigned int len, } static void mg_openssl_init() { +#ifndef _EMSCRIPTEN_ #if OPENSSL_VERSION_NUMBER < 0x10100000L static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int mg_ssl_initialized = 0; @@ -132,6 +135,7 @@ static void mg_openssl_init() { } pthread_mutex_unlock(&mutex); #endif +#endif } int mg_secure_transport_init(int sockfd, const char *cert_file, From 73a83d99e8964e3380ce836fb2c0e7356da62a19 Mon Sep 17 00:00:00 2001 From: Kostas Date: Wed, 19 Jan 2022 14:49:47 +0200 Subject: [PATCH 02/18] Fix missing mg-shared --- include/mgclient.h | 131 ++++++++++++++++++++++++++------------------- src/CMakeLists.txt | 2 +- src/mgwasm.c | 63 ++++++++++++++++++++++ src/mgwasm.h | 16 ++++++ 4 files changed, 156 insertions(+), 56 deletions(-) create mode 100644 src/mgwasm.c create mode 100644 src/mgwasm.h diff --git a/include/mgclient.h b/include/mgclient.h index 7f7082e..273b17e 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -1011,8 +1011,8 @@ mg_date_time_zone_id_tz_id(const mg_date_time_zone_id *date_time_zone_id); /// Creates a copy of the given date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time_zone_id *mg_date_time_zone_id_copy( - const mg_date_time_zone_id *date_time_zone_id); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time_zone_id * +mg_date_time_zone_id_copy(const mg_date_time_zone_id *date_time_zone_id); /// Destroys the given date and time. MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_zone_id_destroy( @@ -1020,8 +1020,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_zone_id_destroy( /// Creates mg_local_date_time from seconds and nanoseconds. /// \return a pointer to mg_local_date_time or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time *mg_local_date_time_make( - int64_t seconds, int64_t nanoseconds); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time * +mg_local_date_time_make(int64_t seconds, int64_t nanoseconds); // /// Returns seconds since Unix epoch. This includes the hours, minutes, seconds /// fields of the local_time. @@ -1035,8 +1035,8 @@ mg_local_date_time_nanoseconds(const mg_local_date_time *local_date_time); /// Creates a copy of the given local date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time *mg_local_date_time_copy( - const mg_local_date_time *local_date_time); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time * +mg_local_date_time_copy(const mg_local_date_time *local_date_time); /// Destroy the given local date and time. MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_date_time_destroy( @@ -1044,66 +1044,82 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_date_time_destroy( /// Creates mg_duration from months, days, seconds and nanoseconds. /// \return a pointer to mg_duration or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_make(int64_t months, int64_t days, - int64_t seconds, - int64_t nanoseconds); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_make( + int64_t months, int64_t days, int64_t seconds, int64_t nanoseconds); /// Returns the months part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_months(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_duration_months(const mg_duration *duration); /// Returns the days part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_days(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_duration_days(const mg_duration *duration); /// Returns the seconds part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_seconds(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_duration_seconds(const mg_duration *duration); /// Returns the nanoseconds part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_duration_nanoseconds(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_duration_nanoseconds(const mg_duration *duration); /// Creates a copy of the given duration. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_copy(const mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_copy( + const mg_duration *duration); /// Destroy the given duration. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_duration_destroy(mg_duration *duration); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_duration_destroy( + mg_duration *duration); /// Returns SRID of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_point_2d_srid(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_point_2d_srid(const mg_point_2d *point_2d); /// Returns the x coordinate of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_x(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_x( + const mg_point_2d *point_2d); /// Returns the y coordinate of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_y(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_y( + const mg_point_2d *point_2d); /// Creates a copy of the given 2D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_2d *mg_point_2d_copy( + const mg_point_2d *point_2d); /// Destroys the given 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_2d_destroy(mg_point_2d *point_2d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_2d_destroy( + mg_point_2d *point_2d); /// Returns SRID of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_point_3d_srid(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +mg_point_3d_srid(const mg_point_3d *point_3d); /// Returns the x coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_x(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_x( + const mg_point_3d *point_3d); /// Returns the y coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_y(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_y( + const mg_point_3d *point_3d); /// Returns the z coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_z(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_z( + const mg_point_3d *point_3d); /// Creates a copy of the given 3D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_3d *mg_point_3d_copy( + const mg_point_3d *point_3d); /// Destroys the given 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_3d_destroy(mg_point_3d *point_3d); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_3d_destroy( + mg_point_3d *point_3d); /// Marks a \ref mg_session ready to execute a new query using \ref /// mg_session_run. @@ -1285,42 +1301,43 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_destroy( mg_session_params *); /// Getters and setters for `mg_session_params` values. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_address(mg_session_params *, - const char *address); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_address( + mg_session_params *, const char *address); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_host( mg_session_params *, const char *host); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_port( mg_session_params *, uint16_t port); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_username(mg_session_params *, - const char *username); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_password(mg_session_params *, - const char *password); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_user_agent(mg_session_params *, - const char *user_agent); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_username( + mg_session_params *, const char *username); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_password( + mg_session_params *, const char *password); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_user_agent( + mg_session_params *, const char *user_agent); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslmode( mg_session_params *, enum mg_sslmode sslmode); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslcert(mg_session_params *, - const char *sslcert); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslkey(mg_session_params *, - const char *sslkey); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslcert( + mg_session_params *, const char *sslcert); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslkey( + mg_session_params *, const char *sslkey); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_callback( mg_session_params *, mg_trust_callback_type trust_callback); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_data(mg_session_params *, - void *trust_data); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_data( + mg_session_params *, void *trust_data); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_address( const mg_session_params *); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_host( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint16_t mg_session_params_get_port(const mg_session_params *); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint16_t +mg_session_params_get_port(const mg_session_params *); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_username( const mg_session_params *); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_password( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_user_agent( - const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_sslmode mg_session_params_get_sslmode( - const mg_session_params *); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char * +mg_session_params_get_user_agent(const mg_session_params *); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_sslmode +mg_session_params_get_sslmode(const mg_session_params *); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslcert( const mg_session_params *); MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslkey( @@ -1344,8 +1361,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void *mg_session_params_get_trust_data( /// \return Returns 0 if connected successfuly, otherwise returns a non-zero /// error code. A more detailed error message can be obtained by using /// \ref mg_session_error on \p session, unless it is set to NULL. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_connect(const mg_session_params *params, - mg_session **session); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_connect( + const mg_session_params *params, mg_session **session); /// Returns the status of \ref mg_session. /// @@ -1359,7 +1376,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_error( mg_session *session); /// Destroys a \ref mg_session and releases all of its resources. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_destroy(mg_session *session); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_destroy( + mg_session *session); /// An object encapsulating a single result row or query execution summary. Its /// lifetime is limited by lifetime of parent \ref mg_session. Also, invoking @@ -1449,8 +1467,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_begin_transaction( /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction(mg_session *session, - mg_result **result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction( + mg_session *session, mg_result **result); /// Rollbacks current Explicit transaction. /// @@ -1460,8 +1478,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction(mg_sessio /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_rollback_transaction(mg_session *session, - mg_result **result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_rollback_transaction( + mg_session *session, mg_result **result); /// Tries to fetch the next query result from \ref mg_session. /// @@ -1496,13 +1514,16 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_pull( mg_session *session, const mg_map *pull_information); /// Returns names of columns output by the current query execution. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_columns(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_columns( + const mg_result *result); /// Returns column values of current result row. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_row(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_row( + const mg_result *result); /// Returns query execution summary. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_result_summary(const mg_result *result); +MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_result_summary( + const mg_result *result); #ifdef __cplusplus } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 621bb1a..83024e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,10 +60,10 @@ if(MGCLIENT_ON_WINDOWS) endif() if(NOT EMSCRIPTEN) + add_library(mgclient-shared STATIC ${mgclient_src_files}) generate_export_header(mgclient-shared BASE_NAME "mgclient" EXPORT_FILE_NAME "mgclient-export.h") - add_library(mgclient-shared STATIC ${mgclient_src_files}) set_target_properties(mgclient-shared PROPERTIES OUTPUT_NAME mgclient SOVERSION ${mgclient_SOVERSION} diff --git a/src/mgwasm.c b/src/mgwasm.c new file mode 100644 index 0000000..b25994f --- /dev/null +++ b/src/mgwasm.c @@ -0,0 +1,63 @@ +#include "mgwasm.h" + +#ifdef __EMSCRIPTEN__ + +#include +#include +#include + +int read_loop(int sock) { + fd_set fdr; + FD_ZERO(&fdr); + FD_SET(sock, &fdr); + int poll = select(sock + 1, &fdr, NULL, NULL, NULL); + if (poll == -1) { + return -1; + } + if (!FD_ISSET(sock, &fdr)) { + return -100; + } + return 1; +} + +int write_loop(int sock) { + fd_set fdw; + FD_ZERO(&fdw); + FD_SET(sock, &fdw); + int poll = select(sock + 1, NULL, &fdw, NULL, NULL); + if (poll == -1) { + return -1; + } + if (!FD_ISSET(sock, &fdw)) { + return -100; + } + return 1; +} + +int yield_until_async_read(int sock, int ms) { + while (1) { + int res = read_loop(sock); + if (res == 1) { + return 1; + } + if (res == -1) { + return -1; + } + emscripten_sleep(ms); + } +} + +int yield_until_async_write(int sock, int ms) { + while (1) { + int res = write_loop(sock); + if (res == 1) { + return 1; + } + if (res == -1) { + return -1; + } + emscripten_sleep(ms); + } +} + +#endif diff --git a/src/mgwasm.h b/src/mgwasm.h new file mode 100644 index 0000000..24559a0 --- /dev/null +++ b/src/mgwasm.h @@ -0,0 +1,16 @@ +#ifndef MGCLIENT_MGWASM_UTIL_H +#define MGCLIENT_MGWASM_UTIL_H + +#ifdef __EMSCRIPTEN__ + +#include "emscripten.h" + +int read_loop(int sock); +int write_loop(int sock); + +int yield_until_async_read(int sock, int ms); +int yield_until_async_write(int sock, int ms); + +#endif + +#endif From 56cf72d1d6a5823d8e77242921734cdfa8c5ca57 Mon Sep 17 00:00:00 2001 From: Kostas Date: Wed, 19 Jan 2022 16:13:25 +0200 Subject: [PATCH 03/18] Fix CMake --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6e743e..f704e84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,13 +33,12 @@ if(WIN32) # "lib;" breaks gtest lib referencing. set(MGCLIENT_FIND_LIBRARY_PREFIXES "lib") elseif(UNIX AND NOT APPLE) - if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") - message(FATAL_ERROR "Unsupported operating system. Please create issue or contribute!") - endif() if(EMSCRIPTEN) message(STATUS "ON LINUX WASM BUILD") - else() + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") message(STATUS "ON LINUX BUILD") + else() + message(FATAL_ERROR "Unsupported operating system. Please create issue or contribute!") endif() set(MGCLIENT_ON_LINUX TRUE) add_definitions(-DMGCLIENT_ON_LINUX) From 7b163f083526bc6179c9ca6d440372a5e0bdd357 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 8 Mar 2022 21:57:12 +0200 Subject: [PATCH 04/18] Added full integration of emscripten with cmake --- CMakeLists.txt | 8 +++++ include/mgclient.h | 4 +++ src/CMakeLists.txt | 85 +++++++++++++++++++++++++++----------------- src/linux/mgsocket.c | 5 ++- src/mgsocket.h | 1 + src/mgtransport.c | 11 ++++-- src/mgtransport.h | 13 +++++++ src/mgwasm.c | 4 +-- 8 files changed, 93 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f704e84..8150851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,14 @@ set_project_c_warnings(project_c_warnings) add_library(project_cpp_warnings INTERFACE) set_project_cpp_warnings(project_cpp_warnings) +if(EMSCRIPTEN) + #same as project_c_warnings but without -O3. In the future we should + #experiment and switch to O3. because it reduces the js output size + #significantly. + set(CMAKE_C_FLAGS_DEBUG "-g -O0-DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") + set(CMAKE_C_FLAGS_RELEASE "-O0 -DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") +endif() + # Set default build type to 'Release' if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") diff --git a/include/mgclient.h b/include/mgclient.h index 273b17e..a32347b 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -15,7 +15,11 @@ #ifndef MGCLIENT_MGCLIENT_H #define MGCLIENT_MGCLIENT_H +#ifdef EMSCRIPTEN +#define MGCLIENT_EXPORT +#else #include "mgclient-export.h" +#endif #ifdef __EMSCRIPTEN__ #include "emscripten.h" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83024e1..73171a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,8 +24,7 @@ set(mgclient_src_files mgsession-decoder.c mgsession-encoder.c mgtransport.c - mgvalue.c - mgwasm.c) + mgvalue.c) if(MGCLIENT_ON_APPLE) list(APPEND mgclient_src_files apple/mgsocket.c) elseif(MGCLIENT_ON_LINUX) @@ -36,34 +35,56 @@ else() message(FATAL_ERROR "Operating system undefined.") endif() -find_package(OpenSSL REQUIRED) - -include(GenerateExportHeader) - -add_library(mgclient-static STATIC ${mgclient_src_files}) -set_target_properties(mgclient-static PROPERTIES - OUTPUT_NAME mgclient) -target_compile_definitions(mgclient-static PUBLIC MGCLIENT_STATIC_DEFINE) -target_include_directories(mgclient-static - PRIVATE - "${PROJECT_SOURCE_DIR}/src" - PUBLIC - "${PROJECT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_BINARY_DIR}" - "${OPENSSL_INCLUDE_DIR}") -target_link_libraries(mgclient-static - PRIVATE - ${OPENSSL_LIBRARIES} project_options project_c_warnings) - -if(MGCLIENT_ON_WINDOWS) - target_link_libraries(mgclient-static PUBLIC ws2_32) +if(NOT EMSCRIPTEN) + find_package(OpenSSL REQUIRED) endif() -if(NOT EMSCRIPTEN) +if(EMSCRIPTEN) + list(APPEND mgclient_src_files mgwasm.c) + add_executable(mgclient ${mgclient_src_files}) + set_target_properties(mgclient PROPERTIES LINK_FLAGS "-o mgclient.js -s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME=\"load_mgclient\" --shared-memory --no-entry -s USE_PTHREADS=1 -s WEBSOCKET_SUBPROTOCOL=\"binary\" -s EXPORTED_FUNCTIONS='_mg_init, _mg_finalize, _mg_session_params_make, _mg_session_params_destroy, _mg_session_params_set_host, _mg_session_params_set_port, _mg_session_params_set_sslmode, _mg_session_error, _mg_session_run, _mg_session_fetch, _mg_session_pull, _mg_connect, _mg_client_version, _mg_result_row' -s EXPORTED_RUNTIME_METHODS=\"ccall, cwrap, getValue, setValue, UTF8ToString\"") + + target_compile_definitions(mgclient PUBLIC MGCLIENT_STATIC_DEFINE) + target_include_directories(mgclient + PRIVATE + "${PROJECT_SOURCE_DIR}/src" + PUBLIC + "${PROJECT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}") + +else() + include(GenerateExportHeader) + + add_library(mgclient-static STATIC ${mgclient_src_files}) + + generate_export_header(mgclient-static + BASE_NAME "mgclient" + EXPORT_FILE_NAME "mgclient-export.h") + + set_target_properties(mgclient-static PROPERTIES + OUTPUT_NAME mgclient) + target_compile_definitions(mgclient-static PUBLIC MGCLIENT_STATIC_DEFINE) + target_include_directories(mgclient-static + PRIVATE + "${PROJECT_SOURCE_DIR}/src" + PUBLIC + "${PROJECT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}" + "${OPENSSL_INCLUDE_DIR}") + target_link_libraries(mgclient-static + PRIVATE + ${OPENSSL_LIBRARIES} project_options project_c_warnings) + + if(MGCLIENT_ON_WINDOWS) + target_link_libraries(mgclient-static PUBLIC ws2_32) + endif() + add_library(mgclient-shared STATIC ${mgclient_src_files}) + generate_export_header(mgclient-shared BASE_NAME "mgclient" EXPORT_FILE_NAME "mgclient-export.h") + set_target_properties(mgclient-shared PROPERTIES OUTPUT_NAME mgclient SOVERSION ${mgclient_SOVERSION} @@ -76,19 +97,17 @@ if(NOT EMSCRIPTEN) "${CMAKE_CURRENT_BINARY_DIR}" "${OPENSSL_INCLUDE_DIR}") target_link_libraries(mgclient-shared PRIVATE ${OPENSSL_LIBRARIES}) -endif() -if(MGCLIENT_ON_WINDOWS) - target_link_libraries(mgclient-shared PUBLIC ws2_32) -endif() + if(MGCLIENT_ON_WINDOWS) + target_link_libraries(mgclient-shared PUBLIC ws2_32) + endif() -generate_export_header(mgclient-static - BASE_NAME "mgclient" - EXPORT_FILE_NAME "mgclient-export.h") + generate_export_header(mgclient-shared + BASE_NAME "mgclient" + EXPORT_FILE_NAME "mgclient-export.h") -include(GNUInstallDirs) + include(GNUInstallDirs) -if(NOT EMSCRIPTEN) install(TARGETS mgclient-static mgclient-shared ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index 92d1a3d..9eb6f68 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "mgsocket.h" + #include #include "mgcommon.h" -#include "mgsocket.h" #ifdef __EMSCRIPTEN__ +#include + #include "emscripten.h" #include "mgwasm.h" #endif diff --git a/src/mgsocket.h b/src/mgsocket.h index 98d80a1..14c3b7e 100644 --- a/src/mgsocket.h +++ b/src/mgsocket.h @@ -30,6 +30,7 @@ extern "C" { #ifdef MGCLIENT_ON_LINUX #include +#include #include #include #include diff --git a/src/mgtransport.c b/src/mgtransport.c index 672049c..4e0c1eb 100644 --- a/src/mgtransport.c +++ b/src/mgtransport.c @@ -105,6 +105,7 @@ void mg_raw_transport_destroy(struct mg_transport *transport) { mg_allocator_free(self->allocator, transport); } +#ifndef __EMSCRIPTEN__ static int print_ssl_error(const char *str, size_t len, void *u) { (void)len; fprintf(stderr, "%s: %s", (char *)u, str); @@ -121,7 +122,6 @@ static char *hex_encode(unsigned char *data, unsigned int len, } static void mg_openssl_init() { -#ifndef _EMSCRIPTEN_ #if OPENSSL_VERSION_NUMBER < 0x10100000L static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int mg_ssl_initialized = 0; @@ -135,7 +135,6 @@ static void mg_openssl_init() { } pthread_mutex_unlock(&mutex); #endif -#endif } int mg_secure_transport_init(int sockfd, const char *cert_file, @@ -323,3 +322,11 @@ void mg_secure_transport_destroy(mg_transport *transport) { mg_allocator_free(self->allocator, self->peer_pubkey_fp); mg_allocator_free(self->allocator, self); } +#else +int mg_secure_transport_init(int sockfd, const char *cert_file, + const char *key_file, + mg_secure_transport **transport, + mg_allocator *allocator) { + return -1; +} +#endif diff --git a/src/mgtransport.h b/src/mgtransport.h index 95f0615..1ff01d7 100644 --- a/src/mgtransport.h +++ b/src/mgtransport.h @@ -19,9 +19,22 @@ extern "C" { #endif +#ifndef __EMSCRIPTEN__ + #include #include #include + +#else +// This is a small hack to allow the current code to compile without openSSL +// support. This is guranteed to work because the API is defined natively by the +// implementation language that consumes the mgclient wasm module. +#define SSL int +#define BIO int +#include + +#endif + #include #include "mgallocator.h" diff --git a/src/mgwasm.c b/src/mgwasm.c index b25994f..c27dd29 100644 --- a/src/mgwasm.c +++ b/src/mgwasm.c @@ -36,6 +36,7 @@ int write_loop(int sock) { int yield_until_async_read(int sock, int ms) { while (1) { + emscripten_sleep(ms); int res = read_loop(sock); if (res == 1) { return 1; @@ -43,12 +44,12 @@ int yield_until_async_read(int sock, int ms) { if (res == -1) { return -1; } - emscripten_sleep(ms); } } int yield_until_async_write(int sock, int ms) { while (1) { + emscripten_sleep(ms); int res = write_loop(sock); if (res == 1) { return 1; @@ -56,7 +57,6 @@ int yield_until_async_write(int sock, int ms) { if (res == -1) { return -1; } - emscripten_sleep(ms); } } From bf1cc157dd76aaf6d365c6ec6046efdbf9e94439 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 8 Mar 2022 23:13:46 +0200 Subject: [PATCH 05/18] Added scripts for wasm deps --- CMakeLists.txt | 5 +++++ wasm/activate.sh | 4 ++++ wasm/install_deps.sh | 5 +++++ 3 files changed, 14 insertions(+) create mode 100644 wasm/activate.sh create mode 100644 wasm/install_deps.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 8150851..e723acd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,13 @@ project(mgclient VERSION 1.3.0) # Minor version increase can also mean ABI incompatibility with previous # versions. IMPORTANT: Take care of the SO version manually. set(mgclient_SOVERSION 2) +set(WASM OFF CACHE BOOL "Compile mgclient for wasm") add_definitions(-DMGCLIENT_VERSION="${mgclient_VERSION}") +if(WASM) + set(CMAKE_TOOLCHAIN_FILE "/opt/mgclient/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") +endif() + # Deal with the operating system. if((NOT UNIX) AND EMSCRIPTEN) message(FATAL_ERROR "WASM build is only supported in Linux") diff --git a/wasm/activate.sh b/wasm/activate.sh new file mode 100644 index 0000000..cab6958 --- /dev/null +++ b/wasm/activate.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +/opt/mgclient/emsdk/emsdk activate latest +source /opt/mgclient/emsdk/emsdk_env.sh diff --git a/wasm/install_deps.sh b/wasm/install_deps.sh new file mode 100644 index 0000000..c077531 --- /dev/null +++ b/wasm/install_deps.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +git clone https://github.com/emscripten-core/emsdk.git /opt/mgclient/emsdk +/opt/mgclient/emsdk/emsdk install latest + From 6d81f924750ab6382d48f044c3cede8b21ab5665 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 8 Mar 2022 23:18:38 +0200 Subject: [PATCH 06/18] updated Readme --- README.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b88717a..15dcebc 100644 --- a/README.md +++ b/README.md @@ -127,18 +127,12 @@ cmake .. -G "MinGW Makefiles" cmake --build . --target install ``` ## Building WASM (linux only) -Compiling `mgclient` requires the Emscripten sdk found in https://github.com/emscripten-core/emsdk and OpenSSL WASM. - - Clone the emsdk repo above and do `./emsdk install latest && ./emsdk activate latest && source ./emsdk_env.sh` - - Clone openssl repo found in https://github.com/openssl/openssl and compile it to WASM with `emconfigure ./Configure -no-asm -no-tests && make -j8` - - Create a build directory under, i.e., `mgclient/build` and then do (replace `PATH_TO` to the right path): - ``` - emcmake cmake .. -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=PATH_TO/openssl/apps/ -DOPENSSL_INCLUDE_DIR=PATH_TO/openssl/include/ -DOPENSSL_SSL_LIBRARY=PATH_TO/openssl/libssl.a -DOPENSSL_CRYPTO_LIBRARY=PATH_TO/openssl/libcrypto.a - - emmake make - - emcc src/libmgclient.a -o mgclient.js -s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME="load_mgclient" --shared-memory --no-entry -s USE_PTHREADS=1 -s SOCKET_DEBUG=1 -s WEBSOCKET_SUBPROTOCOL="binary" -s EXPORTED_FUNCTIONS='_mg_init, _mg_finalize, _mg_session_params_make, _mg_session_params_destroy, _mg_session_params_set_host, _mg_session_params_set_port, _mg_session_params_set_sslmode, _mg_session_error, _mg_session_run, _mg_session_fetch, _mg_session_pull, _mg_connect' -s EXPORTED_RUNTIME_METHODS="ccall,cwrap,getValue,setValue" -L/home/rim/Desktop/openssl/ -lssl -lcrypto - - ``` +Compiling `mgclient` for wasm requires the Emscripten sdk. This is automated in the following steps: + 1. sudo wasm/install_deps.sh + 2. wasm/activate.sh + 3. mkdir build && cd build + 4. cmake .. -DWASM=ON + 5. make Now there should be an `mgclient.js` and an `mgclient.wasm` found in `mgclient/build/` ## Using the library From 6c99edfc6340afa90dc0fbfd982036e0c492cf62 Mon Sep 17 00:00:00 2001 From: Kostas Date: Wed, 9 Mar 2022 19:41:57 +0200 Subject: [PATCH 07/18] Addressed comments and added workflow on gh action --- .github/workflows/ci.yml | 19 +++++++++++++++++++ CMakeLists.txt | 10 +++++----- src/CMakeLists.txt | 12 +++++------- src/linux/mgsocket.c | 15 +++++++++++++-- src/mgclient.c | 9 ++++++--- src/mgsession.c | 2 ++ src/mgtransport.c | 9 +-------- src/mgtransport.h | 11 ++++------- src/mgwasm.h | 6 +++--- wasm/activate.sh | 6 ++++-- wasm/install_deps.sh | 6 +++--- 11 files changed, 65 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c259ec..a93dbde 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,3 +128,22 @@ jobs: cmake .. -G "MinGW Makefiles" -DBUILD_TESTING=ON -DBUILD_TESTING_INTEGRATION=ON -DC_WARNINGS_AS_ERRORS=ON -DCPP_WARNINGS_AS_ERRORS=ON cmake --build . ctest --verbose -R "allocator|value|example_basic|integration_basic" + + build_and_test_linux_wasm: + strategy: + matrix: + platform: [ubuntu-18.04] + runs-on: ${{ matrix.platform }} + env: + MG_VERSION: "1.4.0" + steps: + - name: Set-up repository + uses: actions/checkout@v1 + - name: Install environment + run: | + sudo apt install -y clang-8 clang++-8 + - name: Build with gcc, test and install mgclient + run: | + mkdir build && ./wasm/install_deps.sh && ./wasm/activate.sh && cd build + cmake -DCMAKE_C_COMPILER=clang-8 -DCMAKE_CXX_COMPILER=clang++-8 -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON .. + make diff --git a/CMakeLists.txt b/CMakeLists.txt index e723acd..4215da5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set(WASM OFF CACHE BOOL "Compile mgclient for wasm") add_definitions(-DMGCLIENT_VERSION="${mgclient_VERSION}") if(WASM) - set(CMAKE_TOOLCHAIN_FILE "/opt/mgclient/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") + set(CMAKE_TOOLCHAIN_FILE "./emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") endif() # Deal with the operating system. @@ -45,9 +45,9 @@ elseif(UNIX AND NOT APPLE) else() message(FATAL_ERROR "Unsupported operating system. Please create issue or contribute!") endif() - set(MGCLIENT_ON_LINUX TRUE) - add_definitions(-DMGCLIENT_ON_LINUX) - set(MGCLIENT_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") + set(MGCLIENT_ON_LINUX TRUE) + add_definitions(-DMGCLIENT_ON_LINUX) + set(MGCLIENT_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") elseif(APPLE) message(STATUS "ON APPLE BUILD") set(MGCLIENT_ON_APPLE TRUE) @@ -94,7 +94,7 @@ if(EMSCRIPTEN) #same as project_c_warnings but without -O3. In the future we should #experiment and switch to O3. because it reduces the js output size #significantly. - set(CMAKE_C_FLAGS_DEBUG "-g -O0-DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") + set(CMAKE_C_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Wpedantic -std=gnu11") set(CMAKE_C_FLAGS_RELEASE "-O0 -DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73171a2..5b06744 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,16 +35,11 @@ else() message(FATAL_ERROR "Operating system undefined.") endif() -if(NOT EMSCRIPTEN) - find_package(OpenSSL REQUIRED) -endif() - if(EMSCRIPTEN) list(APPEND mgclient_src_files mgwasm.c) add_executable(mgclient ${mgclient_src_files}) set_target_properties(mgclient PROPERTIES LINK_FLAGS "-o mgclient.js -s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME=\"load_mgclient\" --shared-memory --no-entry -s USE_PTHREADS=1 -s WEBSOCKET_SUBPROTOCOL=\"binary\" -s EXPORTED_FUNCTIONS='_mg_init, _mg_finalize, _mg_session_params_make, _mg_session_params_destroy, _mg_session_params_set_host, _mg_session_params_set_port, _mg_session_params_set_sslmode, _mg_session_error, _mg_session_run, _mg_session_fetch, _mg_session_pull, _mg_connect, _mg_client_version, _mg_result_row' -s EXPORTED_RUNTIME_METHODS=\"ccall, cwrap, getValue, setValue, UTF8ToString\"") - target_compile_definitions(mgclient PUBLIC MGCLIENT_STATIC_DEFINE) target_include_directories(mgclient PRIVATE "${PROJECT_SOURCE_DIR}/src" @@ -53,6 +48,7 @@ if(EMSCRIPTEN) "${CMAKE_CURRENT_BINARY_DIR}") else() + find_package(OpenSSL REQUIRED) include(GenerateExportHeader) add_library(mgclient-static STATIC ${mgclient_src_files}) @@ -79,7 +75,7 @@ else() target_link_libraries(mgclient-static PUBLIC ws2_32) endif() - add_library(mgclient-shared STATIC ${mgclient_src_files}) + add_library(mgclient-shared SHARED ${mgclient_src_files}) generate_export_header(mgclient-shared BASE_NAME "mgclient" @@ -96,7 +92,9 @@ else() "${PROJECT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}" "${OPENSSL_INCLUDE_DIR}") - target_link_libraries(mgclient-shared PRIVATE ${OPENSSL_LIBRARIES}) + target_link_libraries(mgclient-shared + PRIVATE + ${OPENSSL_LIBRARIES} project_options project_c_warnings) if(MGCLIENT_ON_WINDOWS) target_link_libraries(mgclient-shared PUBLIC ws2_32) diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index 9eb6f68..f8106cf 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -55,14 +55,25 @@ int mg_socket_create_handle_error(int sock, mg_session *session) { return MG_SUCCESS; } +static int mg_socket_test_status_is_error(long status) { +#ifdef __EMSCRIPTEN__ + if (status == -1L && errno != EINPROGRESS) { +#else + if (status == -1L) { +#endif + return 1; + } + return 0; +} + int mg_socket_connect(int sock, const struct sockaddr *addr, socklen_t addrlen) { long status = MG_RETRY_ON_EINTR(connect(sock, addr, addrlen)); - if (status == -1L && errno != EINPROGRESS) { + if (mg_socket_test_status_is_error(status)) { return MG_ERROR_SOCKET; } #ifdef __EMSCRIPTEN__ - if (yield_until_async_write(sock, 10) == -1) { + if (yield_until_async_write(sock, 10)) { return MG_ERROR_SOCKET; } #endif diff --git a/src/mgclient.c b/src/mgclient.c index 14bab43..f94902f 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -453,8 +453,7 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, } if (getaddrinfo_status != 0) { #ifdef __EMSCRIPTEN__ - mg_session_set_error(session, "getaddrinfo failed: %s", - "Replace with error"); + mg_session_set_error(session, "getaddrinfo failed: %d", getaddrinfo_status); // Not supported by emscripten: // gai_strerror(getaddrinfo_status)); #else @@ -499,6 +498,7 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, return 0; } +#ifndef __EMSCRIPTEN__ static int get_hostname_and_ip(const struct sockaddr *peer_addr, char *hostname, char *ip, mg_session *session) { // Populate the ip. @@ -539,6 +539,7 @@ static int get_hostname_and_ip(const struct sockaddr *peer_addr, char *hostname, } return 0; } +#endif int mg_connect_ca(const mg_session_params *params, mg_session **session, mg_allocator *allocator) { @@ -570,6 +571,7 @@ int mg_connect_ca(const mg_session_params *params, mg_session **session, goto cleanup; } break; +#ifndef __EMSCRIPTEN__ case MG_SSLMODE_REQUIRE: { mg_secure_transport *ttransport; status = mg_secure_transport_init(sockfd, params->sslcert, params->sslkey, @@ -599,6 +601,7 @@ int mg_connect_ca(const mg_session_params *params, mg_session **session, } break; } +#endif default: // Should not get here. abort(); @@ -705,7 +708,7 @@ int mg_session_run(mg_session *session, const char *query, const mg_map *params, goto fatal_failure; } -#ifdef __EMSCRIPTEN_ +#ifdef __EMSCRIPTEN__ int socket = ((mg_raw_transport *)session->transport)->sockfd; yield_until_async_read(socket, 10); #endif diff --git a/src/mgsession.c b/src/mgsession.c index 407830d..dc11dec 100644 --- a/src/mgsession.c +++ b/src/mgsession.c @@ -27,7 +27,9 @@ #include "mgcommon.h" #include "mgconstants.h" #include "mgsession.h" +#ifdef __EMSCRIPTEN__ #include "mgwasm.h" +#endif int mg_session_status(const mg_session *session) { if (!session) { diff --git a/src/mgtransport.c b/src/mgtransport.c index 4e0c1eb..9090dea 100644 --- a/src/mgtransport.c +++ b/src/mgtransport.c @@ -19,7 +19,7 @@ #include #include #ifdef MGCLIENT_ON_LINUX -#ifndef _EMSCRIPTEN_ +#ifndef __EMSCRIPTEN__ #include #endif #endif // MGCLIENT_ON_LINUX @@ -322,11 +322,4 @@ void mg_secure_transport_destroy(mg_transport *transport) { mg_allocator_free(self->allocator, self->peer_pubkey_fp); mg_allocator_free(self->allocator, self); } -#else -int mg_secure_transport_init(int sockfd, const char *cert_file, - const char *key_file, - mg_secure_transport **transport, - mg_allocator *allocator) { - return -1; -} #endif diff --git a/src/mgtransport.h b/src/mgtransport.h index 1ff01d7..4456322 100644 --- a/src/mgtransport.h +++ b/src/mgtransport.h @@ -24,15 +24,8 @@ extern "C" { #include #include #include - #else -// This is a small hack to allow the current code to compile without openSSL -// support. This is guranteed to work because the API is defined natively by the -// implementation language that consumes the mgclient wasm module. -#define SSL int -#define BIO int #include - #endif #include @@ -54,6 +47,7 @@ typedef struct mg_raw_transport { mg_allocator *allocator; } mg_raw_transport; +#ifndef __EMSCRIPTEN__ typedef struct mg_secure_transport { int (*send)(struct mg_transport *, const char *buf, size_t len); int (*recv)(struct mg_transport *, char *buf, size_t len); @@ -64,6 +58,7 @@ typedef struct mg_secure_transport { char *peer_pubkey_fp; mg_allocator *allocator; } mg_secure_transport; +#endif int mg_transport_send(mg_transport *transport, const char *buf, size_t len); @@ -80,6 +75,7 @@ int mg_raw_transport_recv(struct mg_transport *, char *buf, size_t len); void mg_raw_transport_destroy(struct mg_transport *); +#ifndef __EMSCRIPTEN__ // This function is mocked in tests during linking by using --wrap. ON_APPLE // there is no --wrap. An alternative is to use -alias but if a symbol is // strong linking fails. @@ -88,6 +84,7 @@ MG_ATTRIBUTE_WEAK int mg_secure_transport_init(int sockfd, const char *key_file, mg_secure_transport **transport, mg_allocator *allocator); +#endif int mg_secure_transport_send(mg_transport *, const char *buf, size_t len); diff --git a/src/mgwasm.h b/src/mgwasm.h index 24559a0..645b580 100644 --- a/src/mgwasm.h +++ b/src/mgwasm.h @@ -1,5 +1,5 @@ -#ifndef MGCLIENT_MGWASM_UTIL_H -#define MGCLIENT_MGWASM_UTIL_H +#ifndef MGCLIENT_MGWASM_H +#define MGCLIENT_MGWASM_H #ifdef __EMSCRIPTEN__ @@ -13,4 +13,4 @@ int yield_until_async_write(int sock, int ms); #endif -#endif +#endif /* MGCLIENT_MGWASM_H */ diff --git a/wasm/activate.sh b/wasm/activate.sh index cab6958..dcc0ee5 100644 --- a/wasm/activate.sh +++ b/wasm/activate.sh @@ -1,4 +1,6 @@ #!/bin/bash -/opt/mgclient/emsdk/emsdk activate latest -source /opt/mgclient/emsdk/emsdk_env.sh +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +EMSDK="${DIR}/../build/emsdk" +${EMSDK}/emsdk activate latest +source ${EMSDK}/emsdk_env.sh diff --git a/wasm/install_deps.sh b/wasm/install_deps.sh index c077531..1353649 100644 --- a/wasm/install_deps.sh +++ b/wasm/install_deps.sh @@ -1,5 +1,5 @@ #!/bin/bash -git clone https://github.com/emscripten-core/emsdk.git /opt/mgclient/emsdk -/opt/mgclient/emsdk/emsdk install latest - +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +git clone https://github.com/emscripten-core/emsdk.git ${DIR}/../build/emsdk +${DIR}/../build/emsdk/emsdk install latest From 26c9879540812ac67a8aac48324ad8ea2802ca0e Mon Sep 17 00:00:00 2001 From: Kostas Date: Wed, 9 Mar 2022 19:54:54 +0200 Subject: [PATCH 08/18] workflow patch --- .github/workflows/ci.yml | 9 +++++---- CMakeLists.txt | 12 +++++++----- src/mgwasm.c | 8 ++++---- wasm/activate.sh | 1 - wasm/install_deps.sh | 0 5 files changed, 16 insertions(+), 14 deletions(-) mode change 100644 => 100755 wasm/activate.sh mode change 100644 => 100755 wasm/install_deps.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a93dbde..926caca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,12 +138,13 @@ jobs: MG_VERSION: "1.4.0" steps: - name: Set-up repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Install environment run: | sudo apt install -y clang-8 clang++-8 - - name: Build with gcc, test and install mgclient + + - name: Build with clang run: | - mkdir build && ./wasm/install_deps.sh && ./wasm/activate.sh && cd build - cmake -DCMAKE_C_COMPILER=clang-8 -DCMAKE_CXX_COMPILER=clang++-8 -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON .. + mkdir build && ./wasm/install_deps.sh && source ./wasm/activate.sh && cd build + cmake .. -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON -DWASM=ON make diff --git a/CMakeLists.txt b/CMakeLists.txt index 4215da5..fdd6dcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,17 +14,19 @@ cmake_minimum_required(VERSION 3.8) -project(mgclient VERSION 1.3.0) +if(WASM) + message(STATUS "WASM") + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/build/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") + message(STATUS ${CMAKE_TOOLCHAIN_FILE}) +endif() + +project(mgclient VERSION 1.2.0) # Minor version increase can also mean ABI incompatibility with previous # versions. IMPORTANT: Take care of the SO version manually. set(mgclient_SOVERSION 2) set(WASM OFF CACHE BOOL "Compile mgclient for wasm") add_definitions(-DMGCLIENT_VERSION="${mgclient_VERSION}") -if(WASM) - set(CMAKE_TOOLCHAIN_FILE "./emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") -endif() - # Deal with the operating system. if((NOT UNIX) AND EMSCRIPTEN) message(FATAL_ERROR "WASM build is only supported in Linux") diff --git a/src/mgwasm.c b/src/mgwasm.c index c27dd29..74dd255 100644 --- a/src/mgwasm.c +++ b/src/mgwasm.c @@ -6,7 +6,7 @@ #include #include -int read_loop(int sock) { +int read_loop(const int sock) { fd_set fdr; FD_ZERO(&fdr); FD_SET(sock, &fdr); @@ -20,7 +20,7 @@ int read_loop(int sock) { return 1; } -int write_loop(int sock) { +int write_loop(const int sock) { fd_set fdw; FD_ZERO(&fdw); FD_SET(sock, &fdw); @@ -34,7 +34,7 @@ int write_loop(int sock) { return 1; } -int yield_until_async_read(int sock, int ms) { +int yield_until_async_read(const int sock, const int ms) { while (1) { emscripten_sleep(ms); int res = read_loop(sock); @@ -47,7 +47,7 @@ int yield_until_async_read(int sock, int ms) { } } -int yield_until_async_write(int sock, int ms) { +int yield_until_async_write(const int sock, const int ms) { while (1) { emscripten_sleep(ms); int res = write_loop(sock); diff --git a/wasm/activate.sh b/wasm/activate.sh old mode 100644 new mode 100755 index dcc0ee5..a0f406d --- a/wasm/activate.sh +++ b/wasm/activate.sh @@ -3,4 +3,3 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" EMSDK="${DIR}/../build/emsdk" ${EMSDK}/emsdk activate latest -source ${EMSDK}/emsdk_env.sh diff --git a/wasm/install_deps.sh b/wasm/install_deps.sh old mode 100644 new mode 100755 From fa134971e7f29bb76f0ea4b5a506fb39d353b829 Mon Sep 17 00:00:00 2001 From: Kostas Date: Thu, 10 Mar 2022 16:41:37 +0200 Subject: [PATCH 09/18] Addressed comments and simplified CI --- .github/workflows/ci.yml | 10 ++++------ CMakeLists.txt | 2 -- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 926caca..30dd9d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,17 +134,15 @@ jobs: matrix: platform: [ubuntu-18.04] runs-on: ${{ matrix.platform }} - env: - MG_VERSION: "1.4.0" steps: - name: Set-up repository uses: actions/checkout@v2 - - name: Install environment - run: | - sudo apt install -y clang-8 clang++-8 + # - name: Install environment + # run: | + # sudo apt install -y clang-8 clang++-8 - name: Build with clang run: | - mkdir build && ./wasm/install_deps.sh && source ./wasm/activate.sh && cd build + mkdir build && ./wasm/install_deps.sh && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON -DWASM=ON make diff --git a/CMakeLists.txt b/CMakeLists.txt index fdd6dcb..c025e2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,7 @@ cmake_minimum_required(VERSION 3.8) if(WASM) - message(STATUS "WASM") set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/build/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") - message(STATUS ${CMAKE_TOOLCHAIN_FILE}) endif() project(mgclient VERSION 1.2.0) From 2b8e52b4c3e9ea31dfd8477644ebc02526d11fdd Mon Sep 17 00:00:00 2001 From: Kostas Date: Thu, 10 Mar 2022 16:46:09 +0200 Subject: [PATCH 10/18] fix CI and improvements --- wasm/install_deps.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/wasm/install_deps.sh b/wasm/install_deps.sh index 1353649..3f41cc8 100755 --- a/wasm/install_deps.sh +++ b/wasm/install_deps.sh @@ -3,3 +3,4 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" git clone https://github.com/emscripten-core/emsdk.git ${DIR}/../build/emsdk ${DIR}/../build/emsdk/emsdk install latest +${DIR}/../build/emsdk/emsdk activate latest From b25d731f0d5cb25b9a48ea5eabb8ab3df0e388ef Mon Sep 17 00:00:00 2001 From: Kostas Date: Thu, 10 Mar 2022 16:48:25 +0200 Subject: [PATCH 11/18] removed unused activate.sh --- .github/workflows/ci.yml | 3 --- wasm/activate.sh | 5 ----- 2 files changed, 8 deletions(-) delete mode 100755 wasm/activate.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30dd9d3..156077b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,9 +137,6 @@ jobs: steps: - name: Set-up repository uses: actions/checkout@v2 - # - name: Install environment - # run: | - # sudo apt install -y clang-8 clang++-8 - name: Build with clang run: | diff --git a/wasm/activate.sh b/wasm/activate.sh deleted file mode 100755 index a0f406d..0000000 --- a/wasm/activate.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -EMSDK="${DIR}/../build/emsdk" -${EMSDK}/emsdk activate latest From 918a2f2f8fcb4f6a0cbb56a2aa29e8a109b7dfe2 Mon Sep 17 00:00:00 2001 From: Kostas Date: Thu, 10 Mar 2022 16:51:17 +0200 Subject: [PATCH 12/18] add consistency to ci.yml --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 156077b..09b4417 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,6 +140,8 @@ jobs: - name: Build with clang run: | - mkdir build && ./wasm/install_deps.sh && cd build + mkdir build + ./wasm/install_deps.sh + cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON -DWASM=ON make From dfc58d24520d76825b00409eb0cbc44577c5f577 Mon Sep 17 00:00:00 2001 From: Kostas Date: Thu, 10 Mar 2022 17:43:34 +0200 Subject: [PATCH 13/18] addressed all comments --- CMakeLists.txt | 6 +- README.md | 3 +- include/mgclient.h | 527 ++++++++++++++++++------------------------- src/linux/mgsocket.c | 2 +- src/mgclient.c | 10 +- src/mgsession.c | 5 +- src/mgwasm.c | 20 +- src/mgwasm.h | 8 +- 8 files changed, 253 insertions(+), 328 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c025e2b..eda5653 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,9 +91,9 @@ add_library(project_cpp_warnings INTERFACE) set_project_cpp_warnings(project_cpp_warnings) if(EMSCRIPTEN) - #same as project_c_warnings but without -O3. In the future we should - #experiment and switch to O3. because it reduces the js output size - #significantly. + # same as project_c_warnings but without -O3. In the future we should + # experiment and switch to O3. because it reduces the js output size + # significantly. set(CMAKE_C_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Wpedantic -std=gnu11") set(CMAKE_C_FLAGS_RELEASE "-O0 -DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") endif() diff --git a/README.md b/README.md index 15dcebc..4da2cb7 100644 --- a/README.md +++ b/README.md @@ -128,8 +128,7 @@ cmake --build . --target install ``` ## Building WASM (linux only) Compiling `mgclient` for wasm requires the Emscripten sdk. This is automated in the following steps: - 1. sudo wasm/install_deps.sh - 2. wasm/activate.sh + 1. wasm/install_deps.sh 3. mkdir build && cd build 4. cmake .. -DWASM=ON 5. make diff --git a/include/mgclient.h b/include/mgclient.h index a32347b..0a5e1b3 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -16,15 +16,10 @@ #define MGCLIENT_MGCLIENT_H #ifdef EMSCRIPTEN -#define MGCLIENT_EXPORT -#else -#include "mgclient-export.h" -#endif - -#ifdef __EMSCRIPTEN__ +#define MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE #include "emscripten.h" #else -#define EMSCRIPTEN_KEEPALIVE +#include "mgclient-export.h" #endif #ifdef __cplusplus @@ -142,17 +137,17 @@ extern "C" { /// Client software version. /// /// \return Client version in the major.minor.patch format. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_client_version(); +MGCLIENT_EXPORT const char *mg_client_version(); /// Initializes the client (the whole process). /// Should be called at the beginning of each process using the client. /// /// \return Zero if initialization was successful. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_init(); +MGCLIENT_EXPORT int mg_init(); /// Finalizes the client (the whole process). /// Should be called at the end of each process using the client. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_finalize(); +MGCLIENT_EXPORT void mg_finalize(); /// An enum listing all the types as specified by Bolt protocol. enum mg_value_type { @@ -302,25 +297,24 @@ typedef struct mg_point_3d mg_point_3d; /// Constructs a nil \ref mg_value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_null(); +MGCLIENT_EXPORT mg_value *mg_value_make_null(); /// Constructs a boolean \ref mg_value. /// /// \param val If the parameter is zero, constructed value will be false. /// Otherwise, it will be true. /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_bool(int val); +MGCLIENT_EXPORT mg_value *mg_value_make_bool(int val); /// Constructs an integer \ref mg_value with the given underlying value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_integer( - int64_t val); +MGCLIENT_EXPORT mg_value *mg_value_make_integer(int64_t val); /// Constructs a float \ref mg_value with the given underlying value. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_float(double val); +MGCLIENT_EXPORT mg_value *mg_value_make_float(double val); /// Constructs a string \ref mg_value given a null-terminated string. /// @@ -330,253 +324,225 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_float(double val); /// \param str A null-terminated UTF-8 string. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_string( - const char *str); +MGCLIENT_EXPORT mg_value *mg_value_make_string(const char *str); /// Construct a string \ref mg_value given the underlying \ref mg_string. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_string2( - mg_string *str); +MGCLIENT_EXPORT mg_value *mg_value_make_string2(mg_string *str); /// Constructs a list \ref mg_value given the underlying \ref mg_list. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_list( - mg_list *list); +MGCLIENT_EXPORT mg_value *mg_value_make_list(mg_list *list); /// Constructs a map \ref mg_value given the underlying \ref mg_map. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_map(mg_map *map); +MGCLIENT_EXPORT mg_value *mg_value_make_map(mg_map *map); /// Constructs a node \ref mg_value given the underlying \ref mg_node. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_node( - mg_node *node); +MGCLIENT_EXPORT mg_value *mg_value_make_node(mg_node *node); /// Constructs a relationship \ref mg_value given the underlying /// \ref mg_relationship. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_relationship( - mg_relationship *rel); +MGCLIENT_EXPORT mg_value *mg_value_make_relationship(mg_relationship *rel); /// Constructs an unbound relationship \ref mg_value given the underlying /// \ref mg_unbound_relationship. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value * -mg_value_make_unbound_relationship(mg_unbound_relationship *rel); +MGCLIENT_EXPORT mg_value *mg_value_make_unbound_relationship( + mg_unbound_relationship *rel); /// Constructs a path \ref mg_value given the underlying \ref mg_path. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_path( - mg_path *path); +MGCLIENT_EXPORT mg_value *mg_value_make_path(mg_path *path); /// Constructs a date \ref mg_value given the underlying \ref mg_date. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date( - mg_date *date); +MGCLIENT_EXPORT mg_value *mg_value_make_date(mg_date *date); /// Constructs a time \ref mg_value given the underlying \ref mg_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_time( - mg_time *time); +MGCLIENT_EXPORT mg_value *mg_value_make_time(mg_time *time); /// Constructs a local time \ref mg_value given the underlying \ref /// mg_local_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_local_time( - mg_local_time *local_time); +MGCLIENT_EXPORT mg_value *mg_value_make_local_time(mg_local_time *local_time); /// Constructs a date and time \ref mg_value given the underlying \ref /// mg_date_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date_time( - mg_date_time *date_time); +MGCLIENT_EXPORT mg_value *mg_value_make_date_time(mg_date_time *date_time); /// Constructs a date and time \ref mg_value given the underlying \ref /// mg_date_time_zone_id. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_date_time_zone_id( +MGCLIENT_EXPORT mg_value *mg_value_make_date_time_zone_id( mg_date_time_zone_id *date_time_zone_id); /// Constructs a local date and time \ref mg_value given the underlying \ref /// mg_local_date_time. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_local_date_time( +MGCLIENT_EXPORT mg_value *mg_value_make_local_date_time( mg_local_date_time *local_date_time); /// Constructs a duration \ref mg_value given the underlying \ref mg_duration. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_duration( - mg_duration *duration); +MGCLIENT_EXPORT mg_value *mg_value_make_duration(mg_duration *duration); /// Constructs a 2D point \ref mg_value given the underlying \ref mg_point_2d. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_point_2d( - mg_point_2d *point_2d); +MGCLIENT_EXPORT mg_value *mg_value_make_point_2d(mg_point_2d *point_2d); /// Constructs a 3D point \ref mg_value given the underlying \ref mg_point_3d. /// /// \return Pointer to the newly constructed value or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_make_point_3d( - mg_point_3d *point_3d); +MGCLIENT_EXPORT mg_value *mg_value_make_point_3d(mg_point_3d *point_3d); /// Returns the type of the given \ref mg_value. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_value_type mg_value_get_type( - const mg_value *val); +MGCLIENT_EXPORT enum mg_value_type mg_value_get_type(const mg_value *val); /// Returns non-zero value if value contains true, zero otherwise. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_value_bool(const mg_value *val); +MGCLIENT_EXPORT int mg_value_bool(const mg_value *val); /// Returns the underlying integer value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_value_integer(const mg_value *val); +MGCLIENT_EXPORT int64_t mg_value_integer(const mg_value *val); /// Returns the underlying float value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_value_float(const mg_value *val); +MGCLIENT_EXPORT double mg_value_float(const mg_value *val); /// Returns the underlying \ref mg_string value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_value_string( - const mg_value *val); +MGCLIENT_EXPORT const mg_string *mg_value_string(const mg_value *val); /// Returns the underlying \ref mg_list value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_value_list( - const mg_value *val); +MGCLIENT_EXPORT const mg_list *mg_value_list(const mg_value *val); /// Returns the underlying \ref mg_map value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_value_map( - const mg_value *val); +MGCLIENT_EXPORT const mg_map *mg_value_map(const mg_value *val); /// Returns the underlying \ref mg_node value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_node *mg_value_node( - const mg_value *val); +MGCLIENT_EXPORT const mg_node *mg_value_node(const mg_value *val); /// Returns the underlying \ref mg_relationship value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_relationship * -mg_value_relationship(const mg_value *val); +MGCLIENT_EXPORT const mg_relationship *mg_value_relationship( + const mg_value *val); /// Returns the underlying \ref mg_unbound_relationship value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_unbound_relationship * -mg_value_unbound_relationship(const mg_value *val); +MGCLIENT_EXPORT const mg_unbound_relationship *mg_value_unbound_relationship( + const mg_value *val); /// Returns the underlying \ref mg_path value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_path *mg_value_path( - const mg_value *val); +MGCLIENT_EXPORT const mg_path *mg_value_path(const mg_value *val); /// Returns the underlying \ref mg_date value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date *mg_value_date( - const mg_value *val); +MGCLIENT_EXPORT const mg_date *mg_value_date(const mg_value *val); /// Returns the underlying \ref mg_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_time *mg_value_time( - const mg_value *val); +MGCLIENT_EXPORT const mg_time *mg_value_time(const mg_value *val); /// Returns the underlying \ref mg_local_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_local_time *mg_value_local_time( - const mg_value *val); +MGCLIENT_EXPORT const mg_local_time *mg_value_local_time(const mg_value *val); /// Returns the underlying \ref mg_date_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date_time *mg_value_date_time( - const mg_value *val); +MGCLIENT_EXPORT const mg_date_time *mg_value_date_time(const mg_value *val); /// Returns the underlying \ref mg_date_time_zone_id value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_date_time_zone_id * -mg_value_date_time_zone_id(const mg_value *val); +MGCLIENT_EXPORT const mg_date_time_zone_id *mg_value_date_time_zone_id( + const mg_value *val); /// Returns the underlying \ref mg_local_date_time value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_local_date_time * -mg_value_local_date_time(const mg_value *val); +MGCLIENT_EXPORT const mg_local_date_time *mg_value_local_date_time( + const mg_value *val); /// Returns the underlying \ref mg_duration value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_duration *mg_value_duration( - const mg_value *val); +MGCLIENT_EXPORT const mg_duration *mg_value_duration(const mg_value *val); /// Returns the underlying \ref mg_point_2d value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_point_2d *mg_value_point_2d( - const mg_value *val); +MGCLIENT_EXPORT const mg_point_2d *mg_value_point_2d(const mg_value *val); /// Returns the underlying \ref mg_point_3d value. /// /// Type check should be made first. Accessing the wrong value results in /// undefined behavior. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_point_3d *mg_value_point_3d( - const mg_value *val); +MGCLIENT_EXPORT const mg_point_3d *mg_value_point_3d(const mg_value *val); /// Creates a copy of the given value. /// /// \return Pointer to the copy or NULL if error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_value *mg_value_copy( - const mg_value *val); +MGCLIENT_EXPORT mg_value *mg_value_copy(const mg_value *val); /// Destroys the given value. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_value_destroy(mg_value *val); +MGCLIENT_EXPORT void mg_value_destroy(mg_value *val); /// Constructs a string given a null-terminated string. /// @@ -587,7 +553,7 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_value_destroy(mg_value *val); /// /// \return A pointer to the newly constructed `mg_string` object or \c NULL /// if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_make(const char *str); +MGCLIENT_EXPORT mg_string *mg_string_make(const char *str); /// Constructs a string given its length (in bytes) and contents. /// @@ -598,25 +564,21 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_make(const char *str); /// /// \return A pointer to the newly constructed `mg_string` object or \c NULL /// if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_make2( - uint32_t len, const char *data); +MGCLIENT_EXPORT mg_string *mg_string_make2(uint32_t len, const char *data); /// Returns a pointer to the beginning of data buffer of string \p str. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_string_data( - const mg_string *str); +MGCLIENT_EXPORT const char *mg_string_data(const mg_string *str); /// Returns the length (in bytes) of string \p str. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t -mg_string_size(const mg_string *str); +MGCLIENT_EXPORT uint32_t mg_string_size(const mg_string *str); /// Creates a copy of the given string. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_string *mg_string_copy( - const mg_string *str); +MGCLIENT_EXPORT mg_string *mg_string_copy(const mg_string *str); /// Destroys the given string. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_string_destroy(mg_string *str); +MGCLIENT_EXPORT void mg_string_destroy(mg_string *str); /// Constructs a list that can hold at most \p capacity elements. /// @@ -627,8 +589,7 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_string_destroy(mg_string *str); /// /// \return A pointer to the newly constructed empty list or NULL if an error /// occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_list *mg_list_make_empty( - uint32_t capacity); +MGCLIENT_EXPORT mg_list *mg_list_make_empty(uint32_t capacity); /// Appends an element at the end of the list \p list. /// @@ -640,26 +601,24 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_list *mg_list_make_empty( /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_list_append(mg_list *list, - mg_value *value); +MGCLIENT_EXPORT int mg_list_append(mg_list *list, mg_value *value); /// Returns the number of elements in list \p list. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t mg_list_size(const mg_list *list); +MGCLIENT_EXPORT uint32_t mg_list_size(const mg_list *list); /// Retrieves the element at position \p pos in list \p list. /// /// \return A pointer to required list element. If \p pos is outside of list /// bounds, \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_list_at( - const mg_list *list, uint32_t pos); +MGCLIENT_EXPORT const mg_value *mg_list_at(const mg_list *list, uint32_t pos); /// Creates a copy of the given list. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_list *mg_list_copy(const mg_list *list); +MGCLIENT_EXPORT mg_list *mg_list_copy(const mg_list *list); /// Destroys the given list. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_list_destroy(mg_list *list); +MGCLIENT_EXPORT void mg_list_destroy(mg_list *list); /// Constructs an empty map that can hold at most \p capacity key-value pairs. /// @@ -671,8 +630,7 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_list_destroy(mg_list *list); /// /// \return A pointer to the newly constructed empty map or NULL if an error /// occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_map *mg_map_make_empty( - uint32_t capacity); +MGCLIENT_EXPORT mg_map *mg_map_make_empty(uint32_t capacity); /// Inserts the given key-value pair into the map. /// @@ -693,9 +651,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_map *mg_map_make_empty( /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert(mg_map *map, - const char *key_str, - mg_value *value); +MGCLIENT_EXPORT int mg_map_insert(mg_map *map, const char *key_str, + mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -715,9 +672,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert(mg_map *map, /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert2(mg_map *map, - mg_string *key, - mg_value *value); +MGCLIENT_EXPORT int mg_map_insert2(mg_map *map, mg_string *key, + mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -737,8 +693,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert2(mg_map *map, /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe( - mg_map *map, const char *key_str, mg_value *value); +MGCLIENT_EXPORT int mg_map_insert_unsafe(mg_map *map, const char *key_str, + mg_value *value); /// Inserts the given key-value pair into the map. /// @@ -756,9 +712,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe( /// /// \return The function returns non-zero value if insertion failed, zero /// otherwise. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe2(mg_map *map, - mg_string *key, - mg_value *value); +MGCLIENT_EXPORT int mg_map_insert_unsafe2(mg_map *map, mg_string *key, + mg_value *value); /// Looks up a map value with the given key. /// @@ -768,8 +723,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_map_insert_unsafe2(mg_map *map, /// /// \return If the key is found in the map, the pointer to the corresponding /// \ref mg_value is returned. Otherwise, \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_at( - const mg_map *map, const char *key_str); +MGCLIENT_EXPORT const mg_value *mg_map_at(const mg_map *map, + const char *key_str); /// Looks up a map value with the given key. /// @@ -780,115 +735,106 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_at( /// /// \return If the key is found in the map, the pointer to the corresponding /// \ref mg_value is returned. Otherwise, \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_at2( - const mg_map *map, uint32_t key_size, const char *key_data); +MGCLIENT_EXPORT const mg_value *mg_map_at2(const mg_map *map, uint32_t key_size, + const char *key_data); /// Returns the number of key-value pairs in map \p map. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t mg_map_size(const mg_map *map); +MGCLIENT_EXPORT uint32_t mg_map_size(const mg_map *map); /// Retrieves the key at position \p pos in map \p map. /// /// \return A pointer to required key. If \p pos is outside of map bounds, \c /// NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_map_key_at( - const mg_map *, uint32_t pos); +MGCLIENT_EXPORT const mg_string *mg_map_key_at(const mg_map *, uint32_t pos); /// Retrieves the value at position \p pos in map \p map. /// /// \return A pointer to required value. If \p pos is outside of map bounds, /// \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_value *mg_map_value_at( - const mg_map *, uint32_t pos); +MGCLIENT_EXPORT const mg_value *mg_map_value_at(const mg_map *, uint32_t pos); /// Creates a copy of the given map. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_map *mg_map_copy(const mg_map *map); +MGCLIENT_EXPORT mg_map *mg_map_copy(const mg_map *map); /// Destroys the given map. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_map_destroy(mg_map *map); +MGCLIENT_EXPORT void mg_map_destroy(mg_map *map); /// Returns the ID of node \p node. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_node_id(const mg_node *node); +MGCLIENT_EXPORT int64_t mg_node_id(const mg_node *node); /// Returns the number of labels of node \p node. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t -mg_node_label_count(const mg_node *node); +MGCLIENT_EXPORT uint32_t mg_node_label_count(const mg_node *node); /// Returns the label at position \p pos in node \p node's label list. /// /// \return A pointer to the required label. If \p pos is outside of label list /// bounds, \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_node_label_at( - const mg_node *node, uint32_t pos); +MGCLIENT_EXPORT const mg_string *mg_node_label_at(const mg_node *node, + uint32_t pos); /// Returns property map of node \p node. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_node_properties( - const mg_node *node); +MGCLIENT_EXPORT const mg_map *mg_node_properties(const mg_node *node); /// Creates a copy of the given node. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_node *mg_node_copy(const mg_node *node); +MGCLIENT_EXPORT mg_node *mg_node_copy(const mg_node *node); /// Destroys the given node. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_node_destroy(mg_node *node); +MGCLIENT_EXPORT void mg_node_destroy(mg_node *node); /// Returns the ID of the relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_relationship_id(const mg_relationship *rel); +MGCLIENT_EXPORT int64_t mg_relationship_id(const mg_relationship *rel); /// Returns the ID of the start node of relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_relationship_start_id(const mg_relationship *rel); +MGCLIENT_EXPORT int64_t mg_relationship_start_id(const mg_relationship *rel); /// Returns the ID of the end node of relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_relationship_end_id(const mg_relationship *rel); +MGCLIENT_EXPORT int64_t mg_relationship_end_id(const mg_relationship *rel); /// Returns the type of the relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string *mg_relationship_type( +MGCLIENT_EXPORT const mg_string *mg_relationship_type( const mg_relationship *rel); /// Returns the property map of the relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_relationship_properties( +MGCLIENT_EXPORT const mg_map *mg_relationship_properties( const mg_relationship *rel); /// Creates a copy of the given relationship. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_relationship *mg_relationship_copy( +MGCLIENT_EXPORT mg_relationship *mg_relationship_copy( const mg_relationship *rel); /// Destroys the given relationship. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_relationship_destroy( - mg_relationship *rel); +MGCLIENT_EXPORT void mg_relationship_destroy(mg_relationship *rel); /// Returns the ID of the unbound relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_unbound_relationship_id(const mg_unbound_relationship *rel); /// Returns the type of the unbound relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_string * -mg_unbound_relationship_type(const mg_unbound_relationship *rel); +MGCLIENT_EXPORT const mg_string *mg_unbound_relationship_type( + const mg_unbound_relationship *rel); /// Returns the property map of the unbound relationship \p rel. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map * -mg_unbound_relationship_properties(const mg_unbound_relationship *rel); +MGCLIENT_EXPORT const mg_map *mg_unbound_relationship_properties( + const mg_unbound_relationship *rel); /// Creates a copy of the given unbound relationship. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_unbound_relationship * -mg_unbound_relationship_copy(const mg_unbound_relationship *rel); +MGCLIENT_EXPORT mg_unbound_relationship *mg_unbound_relationship_copy( + const mg_unbound_relationship *rel); /// Destroys the given unbound relationship. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_unbound_relationship_destroy( +MGCLIENT_EXPORT void mg_unbound_relationship_destroy( mg_unbound_relationship *rel); /// Returns the length (the number of edges) of path \p path. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint32_t -mg_path_length(const mg_path *path); +MGCLIENT_EXPORT uint32_t mg_path_length(const mg_path *path); /// Returns the node at position \p pos in the traversal of path \p path. /// @@ -896,8 +842,8 @@ mg_path_length(const mg_path *path); /// /// \return A pointer to the required node. If \p pos is out of path bounds, \c /// NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_node *mg_path_node_at( - const mg_path *path, uint32_t pos); +MGCLIENT_EXPORT const mg_node *mg_path_node_at(const mg_path *path, + uint32_t pos); /// Returns the relationship at position \p pos in traversal of path \p path. /// @@ -905,8 +851,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_node *mg_path_node_at( /// /// \return A pointer to the required relationship. If \p pos is outside of /// path bounds, \c NULL is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_unbound_relationship * -mg_path_relationship_at(const mg_path *path, uint32_t pos); +MGCLIENT_EXPORT const mg_unbound_relationship *mg_path_relationship_at( + const mg_path *path, uint32_t pos); /// Checks if the relationship at position \p pos in traversal of path \p path /// is reversed. @@ -917,213 +863,189 @@ mg_path_relationship_at(const mg_path *path, uint32_t pos); /// underlying relationship in the data graph, and 1 if it is traversed /// in the opposite direction. If \p pos is outside of path bounds, -1 /// is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_path_relationship_reversed_at( - const mg_path *path, uint32_t pos); +MGCLIENT_EXPORT int mg_path_relationship_reversed_at(const mg_path *path, + uint32_t pos); /// Creates a copy of the given path. /// /// \return A pointer to the copy or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_path *mg_path_copy(const mg_path *path); +MGCLIENT_EXPORT mg_path *mg_path_copy(const mg_path *path); /// Destroys the given path. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_path_destroy(mg_path *path); +MGCLIENT_EXPORT void mg_path_destroy(mg_path *path); /// Creates mg_date from days. /// \return a pointer to mg_date or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date *mg_date_make(int64_t days); +MGCLIENT_EXPORT mg_date *mg_date_make(int64_t days); /// Returns days since the Unix epoch. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t mg_date_days(const mg_date *date); +MGCLIENT_EXPORT int64_t mg_date_days(const mg_date *date); /// Creates a copy of the given date. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date *mg_date_copy(const mg_date *date); +MGCLIENT_EXPORT mg_date *mg_date_copy(const mg_date *date); /// Destroys the given date. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_destroy(mg_date *date); +MGCLIENT_EXPORT void mg_date_destroy(mg_date *date); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_time_nanoseconds(const mg_time *time); +MGCLIENT_EXPORT int64_t mg_time_nanoseconds(const mg_time *time); /// Returns time zone offset in seconds from UTC. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_time_tz_offset_seconds(const mg_time *time); +MGCLIENT_EXPORT int64_t mg_time_tz_offset_seconds(const mg_time *time); /// Creates a copy of the given time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_time *mg_time_copy(const mg_time *time); +MGCLIENT_EXPORT mg_time *mg_time_copy(const mg_time *time); /// Destroys the given time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_time_destroy(mg_time *time); +MGCLIENT_EXPORT void mg_time_destroy(mg_time *time); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_local_time_nanoseconds(const mg_local_time *local_time); /// Creates mg_local_time from nanoseconds. /// \return a pointer to mg_local_time or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_time *mg_local_time_make( - int64_t nanoseconds); +MGCLIENT_EXPORT mg_local_time *mg_local_time_make(int64_t nanoseconds); /// Creates a copy of the given local time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_time *mg_local_time_copy( +MGCLIENT_EXPORT mg_local_time *mg_local_time_copy( const mg_local_time *local_time); /// Destroys the given local time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_time_destroy( - mg_local_time *local_time); +MGCLIENT_EXPORT void mg_local_time_destroy(mg_local_time *local_time); /// Returns seconds since Unix epoch. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_date_time_seconds(const mg_date_time *date_time); +MGCLIENT_EXPORT int64_t mg_date_time_seconds(const mg_date_time *date_time); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_date_time_nanoseconds(const mg_date_time *date_time); +MGCLIENT_EXPORT int64_t mg_date_time_nanoseconds(const mg_date_time *date_time); /// Returns time zone offset in minutes from UTC. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_date_time_tz_offset_minutes(const mg_date_time *date_time); /// Creates a copy of the given date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time *mg_date_time_copy( - const mg_date_time *date_time); +MGCLIENT_EXPORT mg_date_time *mg_date_time_copy(const mg_date_time *date_time); /// Destroys the given date and time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_destroy( - mg_date_time *date_time); +MGCLIENT_EXPORT void mg_date_time_destroy(mg_date_time *date_time); /// Returns seconds since Unix epoch. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_date_time_zone_id_seconds(const mg_date_time_zone_id *date_time_zone_id); /// Returns nanoseconds since midnight. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_date_time_zone_id_nanoseconds(const mg_date_time_zone_id *date_time_zone_id); /// Returns time zone represented by the identifier. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_date_time_zone_id_tz_id(const mg_date_time_zone_id *date_time_zone_id); /// Creates a copy of the given date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_date_time_zone_id * -mg_date_time_zone_id_copy(const mg_date_time_zone_id *date_time_zone_id); +MGCLIENT_EXPORT mg_date_time_zone_id *mg_date_time_zone_id_copy( + const mg_date_time_zone_id *date_time_zone_id); /// Destroys the given date and time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_date_time_zone_id_destroy( +MGCLIENT_EXPORT void mg_date_time_zone_id_destroy( mg_date_time_zone_id *date_time_zone_id); /// Creates mg_local_date_time from seconds and nanoseconds. /// \return a pointer to mg_local_date_time or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time * -mg_local_date_time_make(int64_t seconds, int64_t nanoseconds); +MGCLIENT_EXPORT mg_local_date_time *mg_local_date_time_make( + int64_t seconds, int64_t nanoseconds); // /// Returns seconds since Unix epoch. This includes the hours, minutes, seconds /// fields of the local_time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_local_date_time_seconds(const mg_local_date_time *local_date_time); /// Returns subseconds of the local_time field as nanoseconds. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t +MGCLIENT_EXPORT int64_t mg_local_date_time_nanoseconds(const mg_local_date_time *local_date_time); /// Creates a copy of the given local date and time. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_local_date_time * -mg_local_date_time_copy(const mg_local_date_time *local_date_time); +MGCLIENT_EXPORT mg_local_date_time *mg_local_date_time_copy( + const mg_local_date_time *local_date_time); /// Destroy the given local date and time. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_local_date_time_destroy( +MGCLIENT_EXPORT void mg_local_date_time_destroy( mg_local_date_time *local_date_time); /// Creates mg_duration from months, days, seconds and nanoseconds. /// \return a pointer to mg_duration or NULL if an error occurred. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_make( - int64_t months, int64_t days, int64_t seconds, int64_t nanoseconds); +MGCLIENT_EXPORT mg_duration *mg_duration_make(int64_t months, int64_t days, + int64_t seconds, + int64_t nanoseconds); /// Returns the months part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_duration_months(const mg_duration *duration); +MGCLIENT_EXPORT int64_t mg_duration_months(const mg_duration *duration); /// Returns the days part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_duration_days(const mg_duration *duration); +MGCLIENT_EXPORT int64_t mg_duration_days(const mg_duration *duration); /// Returns the seconds part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_duration_seconds(const mg_duration *duration); +MGCLIENT_EXPORT int64_t mg_duration_seconds(const mg_duration *duration); /// Returns the nanoseconds part of the temporal amount. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_duration_nanoseconds(const mg_duration *duration); +MGCLIENT_EXPORT int64_t mg_duration_nanoseconds(const mg_duration *duration); /// Creates a copy of the given duration. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_duration *mg_duration_copy( - const mg_duration *duration); +MGCLIENT_EXPORT mg_duration *mg_duration_copy(const mg_duration *duration); /// Destroy the given duration. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_duration_destroy( - mg_duration *duration); +MGCLIENT_EXPORT void mg_duration_destroy(mg_duration *duration); /// Returns SRID of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_point_2d_srid(const mg_point_2d *point_2d); +MGCLIENT_EXPORT int64_t mg_point_2d_srid(const mg_point_2d *point_2d); /// Returns the x coordinate of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_x( - const mg_point_2d *point_2d); +MGCLIENT_EXPORT double mg_point_2d_x(const mg_point_2d *point_2d); /// Returns the y coordinate of the 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_2d_y( - const mg_point_2d *point_2d); +MGCLIENT_EXPORT double mg_point_2d_y(const mg_point_2d *point_2d); /// Creates a copy of the given 2D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_2d *mg_point_2d_copy( - const mg_point_2d *point_2d); +MGCLIENT_EXPORT mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d); /// Destroys the given 2D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_2d_destroy( - mg_point_2d *point_2d); +MGCLIENT_EXPORT void mg_point_2d_destroy(mg_point_2d *point_2d); /// Returns SRID of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int64_t -mg_point_3d_srid(const mg_point_3d *point_3d); +MGCLIENT_EXPORT int64_t mg_point_3d_srid(const mg_point_3d *point_3d); /// Returns the x coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_x( - const mg_point_3d *point_3d); +MGCLIENT_EXPORT double mg_point_3d_x(const mg_point_3d *point_3d); /// Returns the y coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_y( - const mg_point_3d *point_3d); +MGCLIENT_EXPORT double mg_point_3d_y(const mg_point_3d *point_3d); /// Returns the z coordinate of the 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE double mg_point_3d_z( - const mg_point_3d *point_3d); +MGCLIENT_EXPORT double mg_point_3d_z(const mg_point_3d *point_3d); /// Creates a copy of the given 3D point. /// /// \return A pointer to the copy or NULL if an error occured. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_point_3d *mg_point_3d_copy( - const mg_point_3d *point_3d); +MGCLIENT_EXPORT mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d); /// Destroys the given 3D point. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_point_3d_destroy( - mg_point_3d *point_3d); +MGCLIENT_EXPORT void mg_point_3d_destroy(mg_point_3d *point_3d); /// Marks a \ref mg_session ready to execute a new query using \ref /// mg_session_run. @@ -1297,58 +1219,55 @@ typedef int (*mg_trust_callback_type)(const char *, const char *, const char *, const char *, void *); /// Creates a new `mg_session_params` object. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_session_params * -mg_session_params_make(); +MGCLIENT_EXPORT mg_session_params *mg_session_params_make(); /// Destroys a `mg_session_params` object. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_destroy( - mg_session_params *); +MGCLIENT_EXPORT void mg_session_params_destroy(mg_session_params *); /// Getters and setters for `mg_session_params` values. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_address( - mg_session_params *, const char *address); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_host( - mg_session_params *, const char *host); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_port( - mg_session_params *, uint16_t port); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_username( - mg_session_params *, const char *username); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_password( - mg_session_params *, const char *password); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_user_agent( - mg_session_params *, const char *user_agent); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslmode( - mg_session_params *, enum mg_sslmode sslmode); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslcert( - mg_session_params *, const char *sslcert); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_sslkey( - mg_session_params *, const char *sslkey); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_callback( +MGCLIENT_EXPORT void mg_session_params_set_address(mg_session_params *, + const char *address); +MGCLIENT_EXPORT void mg_session_params_set_host(mg_session_params *, + const char *host); +MGCLIENT_EXPORT void mg_session_params_set_port(mg_session_params *, + uint16_t port); +MGCLIENT_EXPORT void mg_session_params_set_username(mg_session_params *, + const char *username); +MGCLIENT_EXPORT void mg_session_params_set_password(mg_session_params *, + const char *password); +MGCLIENT_EXPORT void mg_session_params_set_user_agent(mg_session_params *, + const char *user_agent); +MGCLIENT_EXPORT void mg_session_params_set_sslmode(mg_session_params *, + enum mg_sslmode sslmode); +MGCLIENT_EXPORT void mg_session_params_set_sslcert(mg_session_params *, + const char *sslcert); +MGCLIENT_EXPORT void mg_session_params_set_sslkey(mg_session_params *, + const char *sslkey); +MGCLIENT_EXPORT void mg_session_params_set_trust_callback( mg_session_params *, mg_trust_callback_type trust_callback); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_params_set_trust_data( - mg_session_params *, void *trust_data); +MGCLIENT_EXPORT void mg_session_params_set_trust_data(mg_session_params *, + void *trust_data); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_address( +MGCLIENT_EXPORT const char *mg_session_params_get_address( + const mg_session_params *); +MGCLIENT_EXPORT const char *mg_session_params_get_host( + const mg_session_params *); +MGCLIENT_EXPORT uint16_t mg_session_params_get_port(const mg_session_params *); +MGCLIENT_EXPORT const char *mg_session_params_get_username( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_host( +MGCLIENT_EXPORT const char *mg_session_params_get_password( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE uint16_t -mg_session_params_get_port(const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_username( +MGCLIENT_EXPORT const char *mg_session_params_get_user_agent( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_password( +MGCLIENT_EXPORT enum mg_sslmode mg_session_params_get_sslmode( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char * -mg_session_params_get_user_agent(const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE enum mg_sslmode -mg_session_params_get_sslmode(const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslcert( +MGCLIENT_EXPORT const char *mg_session_params_get_sslcert( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_params_get_sslkey( +MGCLIENT_EXPORT const char *mg_session_params_get_sslkey( const mg_session_params *); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE mg_trust_callback_type +MGCLIENT_EXPORT mg_trust_callback_type mg_session_params_get_trust_callback(const mg_session_params *params); -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void *mg_session_params_get_trust_data( +MGCLIENT_EXPORT void *mg_session_params_get_trust_data( const mg_session_params *); /// Makes a new connection to the database server. @@ -1365,23 +1284,20 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void *mg_session_params_get_trust_data( /// \return Returns 0 if connected successfuly, otherwise returns a non-zero /// error code. A more detailed error message can be obtained by using /// \ref mg_session_error on \p session, unless it is set to NULL. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_connect( - const mg_session_params *params, mg_session **session); +MGCLIENT_EXPORT int mg_connect(const mg_session_params *params, + mg_session **session); /// Returns the status of \ref mg_session. /// /// \return One of \ref MG_SESSION_READY, \ref MG_SESSION_EXECUTING, /// \ref MG_SESSION_BAD. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_status( - const mg_session *session); +MGCLIENT_EXPORT int mg_session_status(const mg_session *session); /// Obtains the error message stored in \ref mg_session (if any). -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const char *mg_session_error( - mg_session *session); +MGCLIENT_EXPORT const char *mg_session_error(mg_session *session); /// Destroys a \ref mg_session and releases all of its resources. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE void mg_session_destroy( - mg_session *session); +MGCLIENT_EXPORT void mg_session_destroy(mg_session *session); /// An object encapsulating a single result row or query execution summary. Its /// lifetime is limited by lifetime of parent \ref mg_session. Also, invoking @@ -1429,9 +1345,10 @@ typedef struct mg_result mg_result; /// if an Explicit transaction was started. /// \return Returns 0 if query was submitted for execution successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_run( - mg_session *session, const char *query, const mg_map *params, - const mg_map *extra_run_information, const mg_list **columns, int64_t *qid); +MGCLIENT_EXPORT int mg_session_run(mg_session *session, const char *query, + const mg_map *params, + const mg_map *extra_run_information, + const mg_list **columns, int64_t *qid); /// Starts an Explicit transaction on the server. /// @@ -1460,7 +1377,7 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_run( /// database. /// \return Returns 0 if the transaction was started successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_begin_transaction( +MGCLIENT_EXPORT int mg_session_begin_transaction( mg_session *session, const mg_map *extra_run_information); /// Commits current Explicit transaction. @@ -1471,8 +1388,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_begin_transaction( /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction( - mg_session *session, mg_result **result); +MGCLIENT_EXPORT int mg_session_commit_transaction(mg_session *session, + mg_result **result); /// Rollbacks current Explicit transaction. /// @@ -1482,8 +1399,8 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_commit_transaction( /// if it was successful. /// \return Returns 0 if the transaction was ended successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_rollback_transaction( - mg_session *session, mg_result **result); +MGCLIENT_EXPORT int mg_session_rollback_transaction(mg_session *session, + mg_result **result); /// Tries to fetch the next query result from \ref mg_session. /// @@ -1496,8 +1413,7 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_rollback_transaction( /// no more result rows and that the query execution summary was stored /// in \p result. Its contents may be accessed using \ref /// mg_result_summary. On failure, a non-zero exit code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_fetch(mg_session *session, - mg_result **result); +MGCLIENT_EXPORT int mg_session_fetch(mg_session *session, mg_result **result); /// Tries to pull results of a statement. /// @@ -1514,20 +1430,17 @@ MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_fetch(mg_session *session, /// is only for Explicit transactions. /// \return Returns 0 if the result was pulled successfuly. /// Otherwise, a non-zero error code is returned. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE int mg_session_pull( - mg_session *session, const mg_map *pull_information); +MGCLIENT_EXPORT int mg_session_pull(mg_session *session, + const mg_map *pull_information); /// Returns names of columns output by the current query execution. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_columns( - const mg_result *result); +MGCLIENT_EXPORT const mg_list *mg_result_columns(const mg_result *result); /// Returns column values of current result row. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_list *mg_result_row( - const mg_result *result); +MGCLIENT_EXPORT const mg_list *mg_result_row(const mg_result *result); /// Returns query execution summary. -MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE const mg_map *mg_result_summary( - const mg_result *result); +MGCLIENT_EXPORT const mg_map *mg_result_summary(const mg_result *result); #ifdef __cplusplus } diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index f8106cf..a4fcb96 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -73,7 +73,7 @@ int mg_socket_connect(int sock, const struct sockaddr *addr, return MG_ERROR_SOCKET; } #ifdef __EMSCRIPTEN__ - if (yield_until_async_write(sock, 10)) { + if (mg_yield_until_async_write_sock(sock)) { return MG_ERROR_SOCKET; } #endif diff --git a/src/mgclient.c b/src/mgclient.c index f94902f..45a1955 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -34,7 +34,7 @@ const char *mg_client_version() { return MGCLIENT_VERSION; } -int EMSCRIPTEN_KEEPALIVE mg_init() { return mg_socket_init(); } +int mg_init() { return mg_socket_init(); } void mg_finalize() { mg_socket_finalize(); } @@ -209,8 +209,7 @@ static int mg_bolt_handshake(mg_session *session) { const uint32_t VERSION_1 = htobe32(1); const uint32_t VERSION_4_1 = htobe32(0x0104); #ifdef __EMSCRIPTEN__ - int socket = ((mg_raw_transport *)session->transport)->sockfd; - yield_until_async_write(socket, 10); + mg_yield_until_async_write(session->transport); #endif if (mg_transport_send(session->transport, MG_HANDSHAKE_MAGIC, strlen(MG_HANDSHAKE_MAGIC)) != 0 || @@ -224,7 +223,7 @@ static int mg_bolt_handshake(mg_session *session) { uint32_t server_version; #ifdef __EMSCRIPTEN__ - yield_until_async_read(socket, 10); + mg_yield_until_async_read(session->transport); #endif if (mg_transport_recv(session->transport, (char *)&server_version, 4) != 0) { mg_session_set_error(session, "failed to receive handshake response"); @@ -709,8 +708,7 @@ int mg_session_run(mg_session *session, const char *query, const mg_map *params, } #ifdef __EMSCRIPTEN__ - int socket = ((mg_raw_transport *)session->transport)->sockfd; - yield_until_async_read(socket, 10); + mg_yield_until_async_read(session->transport); #endif status = mg_session_receive_message(session); if (status != 0) { diff --git a/src/mgsession.c b/src/mgsession.c index dc11dec..8a89c9f 100644 --- a/src/mgsession.c +++ b/src/mgsession.c @@ -231,8 +231,7 @@ int mg_session_ensure_space_for_chunk(mg_session *session, size_t chunk_size) { int mg_session_read_chunk(mg_session *session) { uint16_t chunk_size; #ifdef __EMSCRIPTEN__ - int socket = ((mg_raw_transport *)session->transport)->sockfd; - yield_until_async_read(socket, 10); + mg_yield_until_async_read(session->transport); #endif if (mg_transport_recv(session->transport, (char *)&chunk_size, 2) != 0) { mg_session_set_error(session, "failed to receive chunk size"); @@ -249,7 +248,7 @@ int mg_session_read_chunk(mg_session *session) { } } #ifdef __EMSCRIPTEN__ - yield_until_async_read(socket, 10); + mg_yield_until_async_read(session->transport); #endif if (mg_transport_recv(session->transport, session->in_buffer + session->in_end, diff --git a/src/mgwasm.c b/src/mgwasm.c index 74dd255..623b1ab 100644 --- a/src/mgwasm.c +++ b/src/mgwasm.c @@ -34,9 +34,11 @@ int write_loop(const int sock) { return 1; } -int yield_until_async_read(const int sock, const int ms) { +static const size_t DELAY_MS = 10; + +int mg_yield_until_async_read_sock(const int sock) { while (1) { - emscripten_sleep(ms); + emscripten_sleep(DELAY_MS); int res = read_loop(sock); if (res == 1) { return 1; @@ -47,9 +49,9 @@ int yield_until_async_read(const int sock, const int ms) { } } -int yield_until_async_write(const int sock, const int ms) { +int mg_yield_until_async_write_sock(const int sock) { while (1) { - emscripten_sleep(ms); + emscripten_sleep(DELAY_MS); int res = write_loop(sock); if (res == 1) { return 1; @@ -60,4 +62,14 @@ int yield_until_async_write(const int sock, const int ms) { } } +int mg_yield_until_async_read(const mg_transport *transport) { + int sock = ((mg_raw_transport *)transport)->sockfd; + return mg_yield_until_async_read_sock(sock); +} + +int mg_yield_until_async_write(const mg_transport *transport) { + int sock = ((mg_raw_transport *)transport)->sockfd; + return mg_yield_until_async_write_sock(sock); +} + #endif diff --git a/src/mgwasm.h b/src/mgwasm.h index 645b580..61b4f79 100644 --- a/src/mgwasm.h +++ b/src/mgwasm.h @@ -4,12 +4,16 @@ #ifdef __EMSCRIPTEN__ #include "emscripten.h" +#include "mgtransport.h" int read_loop(int sock); int write_loop(int sock); -int yield_until_async_read(int sock, int ms); -int yield_until_async_write(int sock, int ms); +int mg_yield_until_async_read_sock(int sock); +int mg_yield_until_async_write_sock(int sock); + +int mg_yield_until_async_read(const mg_transport *transport); +int mg_yield_until_async_write(const mg_transport *transport); #endif From d30b0220c9915148aa567244c242eaf6ec514a33 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 15 Mar 2022 14:14:55 +0200 Subject: [PATCH 14/18] Addressed comments and fixed refactoring bug --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 3 +-- src/linux/mgsocket.c | 5 ++--- src/mgclient.c | 14 ++++---------- src/mgsession.c | 9 +++------ src/mgtransport.c | 39 +++++++++++++++++++++++++++++++++++++++ src/mgtransport.h | 20 ++++++++++++++++---- src/mgwasm.c | 42 +++++++++++++----------------------------- src/mgwasm.h | 17 ++--------------- 9 files changed, 81 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eda5653..05e7990 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ if(EMSCRIPTEN) # experiment and switch to O3. because it reduces the js output size # significantly. set(CMAKE_C_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Wpedantic -std=gnu11") - set(CMAKE_C_FLAGS_RELEASE "-O0 -DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") + set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG -Wall -Wextra -Wpedantic -std=gnu11") endif() # Set default build type to 'Release' diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b06744..e0a8dd9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,7 +38,7 @@ endif() if(EMSCRIPTEN) list(APPEND mgclient_src_files mgwasm.c) add_executable(mgclient ${mgclient_src_files}) - set_target_properties(mgclient PROPERTIES LINK_FLAGS "-o mgclient.js -s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME=\"load_mgclient\" --shared-memory --no-entry -s USE_PTHREADS=1 -s WEBSOCKET_SUBPROTOCOL=\"binary\" -s EXPORTED_FUNCTIONS='_mg_init, _mg_finalize, _mg_session_params_make, _mg_session_params_destroy, _mg_session_params_set_host, _mg_session_params_set_port, _mg_session_params_set_sslmode, _mg_session_error, _mg_session_run, _mg_session_fetch, _mg_session_pull, _mg_connect, _mg_client_version, _mg_result_row' -s EXPORTED_RUNTIME_METHODS=\"ccall, cwrap, getValue, setValue, UTF8ToString\"") + set_target_properties(mgclient PROPERTIES LINK_FLAGS "-s ASYNCIFY=1 -s MODULARIZE -s EXPORT_NAME=\"load_mgclient\" --shared-memory --no-entry -s USE_PTHREADS=1 -s WEBSOCKET_SUBPROTOCOL=\"binary\" -s EXPORTED_RUNTIME_METHODS=\"ccall, cwrap, getValue, setValue, UTF8ToString, allocateUTF8\"") target_include_directories(mgclient PRIVATE @@ -46,7 +46,6 @@ if(EMSCRIPTEN) PUBLIC "${PROJECT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}") - else() find_package(OpenSSL REQUIRED) include(GenerateExportHeader) diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index a4fcb96..eb42f84 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -14,13 +14,12 @@ #include "mgsocket.h" +#include #include #include "mgcommon.h" #ifdef __EMSCRIPTEN__ -#include - #include "emscripten.h" #include "mgwasm.h" #endif @@ -73,7 +72,7 @@ int mg_socket_connect(int sock, const struct sockaddr *addr, return MG_ERROR_SOCKET; } #ifdef __EMSCRIPTEN__ - if (mg_yield_until_async_write_sock(sock)) { + if (mg_wasm_suspend_until_ready_to_write(sock) == -1) { return MG_ERROR_SOCKET; } #endif diff --git a/src/mgclient.c b/src/mgclient.c index 45a1955..f154835 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -26,6 +26,7 @@ #include "mgmessage.h" #include "mgsession.h" #include "mgsocket.h" +#include "mgtransport.h" #include "mgvalue.h" #ifdef __EMSCRIPTEN__ @@ -208,9 +209,7 @@ static int mg_bolt_handshake(mg_session *session) { const uint32_t VERSION_NONE = htobe32(0); const uint32_t VERSION_1 = htobe32(1); const uint32_t VERSION_4_1 = htobe32(0x0104); -#ifdef __EMSCRIPTEN__ - mg_yield_until_async_write(session->transport); -#endif + mg_transport_suspend_until_ready_to_write(session->transport); if (mg_transport_send(session->transport, MG_HANDSHAKE_MAGIC, strlen(MG_HANDSHAKE_MAGIC)) != 0 || mg_transport_send(session->transport, (char *)&VERSION_4_1, 4) != 0 || @@ -222,9 +221,7 @@ static int mg_bolt_handshake(mg_session *session) { } uint32_t server_version; -#ifdef __EMSCRIPTEN__ - mg_yield_until_async_read(session->transport); -#endif + mg_transport_suspend_until_ready_to_read(session->transport); if (mg_transport_recv(session->transport, (char *)&server_version, 4) != 0) { mg_session_set_error(session, "failed to receive handshake response"); return MG_ERROR_RECV_FAILED; @@ -439,7 +436,6 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, char portstr[6]; sprintf(portstr, "%" PRIu16, params->port); - int getaddrinfo_status; if (params->host) { getaddrinfo_status = getaddrinfo(params->host, portstr, &hints, &addr_list); @@ -707,9 +703,7 @@ int mg_session_run(mg_session *session, const char *query, const mg_map *params, goto fatal_failure; } -#ifdef __EMSCRIPTEN__ - mg_yield_until_async_read(session->transport); -#endif + mg_transport_suspend_until_ready_to_read(session->transport); status = mg_session_receive_message(session); if (status != 0) { goto fatal_failure; diff --git a/src/mgsession.c b/src/mgsession.c index 8a89c9f..a50bd57 100644 --- a/src/mgsession.c +++ b/src/mgsession.c @@ -27,6 +27,7 @@ #include "mgcommon.h" #include "mgconstants.h" #include "mgsession.h" +#include "mgtransport.h" #ifdef __EMSCRIPTEN__ #include "mgwasm.h" #endif @@ -230,9 +231,7 @@ int mg_session_ensure_space_for_chunk(mg_session *session, size_t chunk_size) { int mg_session_read_chunk(mg_session *session) { uint16_t chunk_size; -#ifdef __EMSCRIPTEN__ - mg_yield_until_async_read(session->transport); -#endif + mg_transport_suspend_until_ready_to_read(session->transport); if (mg_transport_recv(session->transport, (char *)&chunk_size, 2) != 0) { mg_session_set_error(session, "failed to receive chunk size"); return MG_ERROR_RECV_FAILED; @@ -247,9 +246,7 @@ int mg_session_read_chunk(mg_session *session) { return status; } } -#ifdef __EMSCRIPTEN__ - mg_yield_until_async_read(session->transport); -#endif + mg_transport_suspend_until_ready_to_read(session->transport); if (mg_transport_recv(session->transport, session->in_buffer + session->in_end, chunk_size) != 0) { diff --git a/src/mgtransport.c b/src/mgtransport.c index 9090dea..3982d24 100644 --- a/src/mgtransport.c +++ b/src/mgtransport.c @@ -28,6 +28,7 @@ #include "mgclient.h" #include "mgcommon.h" #include "mgsocket.h" +#include "mgwasm.h" int mg_init_ssl = 1; @@ -43,6 +44,18 @@ void mg_transport_destroy(mg_transport *transport) { transport->destroy(transport); } +void mg_transport_suspend_until_ready_to_read(struct mg_transport *transport) { + if (transport->suspend_until_ready_to_read) { + transport->suspend_until_ready_to_read(transport); + } +} + +void mg_transport_suspend_until_ready_to_write(struct mg_transport *transport) { + if (transport->suspend_until_ready_to_write) { + transport->suspend_until_ready_to_write(transport); + } +} + int mg_raw_transport_init(int sockfd, mg_raw_transport **transport, mg_allocator *allocator) { mg_raw_transport *ttransport = @@ -54,6 +67,10 @@ int mg_raw_transport_init(int sockfd, mg_raw_transport **transport, ttransport->send = mg_raw_transport_send; ttransport->recv = mg_raw_transport_recv; ttransport->destroy = mg_raw_transport_destroy; + ttransport->suspend_until_ready_to_read = + mg_raw_transport_suspend_until_ready_to_read; + ttransport->suspend_until_ready_to_write = + mg_raw_transport_suspend_until_ready_to_write; ttransport->allocator = allocator; *transport = ttransport; return 0; @@ -105,6 +122,26 @@ void mg_raw_transport_destroy(struct mg_transport *transport) { mg_allocator_free(self->allocator, transport); } +void mg_raw_transport_suspend_until_ready_to_read( + struct mg_transport *transport) { +#ifdef __EMSCRIPTEN__ + const int sock = ((mg_raw_transport *)transport)->sockfd; + mg_wasm_suspend_until_ready_to_read(sock); +#else + (void)transport; +#endif +} + +void mg_raw_transport_suspend_until_ready_to_write( + struct mg_transport *transport) { +#ifdef __EMSCRIPTEN__ + const int sock = ((mg_raw_transport *)transport)->sockfd; + mg_wasm_suspend_until_ready_to_write(sock); +#else + (void)transport; +#endif +} + #ifndef __EMSCRIPTEN__ static int print_ssl_error(const char *str, size_t len, void *u) { (void)len; @@ -231,6 +268,8 @@ int mg_secure_transport_init(int sockfd, const char *cert_file, hex_encode(peer_pubkey_fp, peer_pubkey_fp_len, allocator); ttransport->send = mg_secure_transport_send; ttransport->recv = mg_secure_transport_recv; + ttransport->suspend_until_ready_to_read = NULL; + ttransport->suspend_until_ready_to_write = NULL; ttransport->destroy = mg_secure_transport_destroy; ttransport->allocator = allocator; *transport = ttransport; diff --git a/src/mgtransport.h b/src/mgtransport.h index 4456322..615b0f5 100644 --- a/src/mgtransport.h +++ b/src/mgtransport.h @@ -20,15 +20,13 @@ extern "C" { #endif #ifndef __EMSCRIPTEN__ - #include #include #include -#else -#include #endif #include +#include #include "mgallocator.h" #include "mgcommon.h" @@ -37,12 +35,16 @@ typedef struct mg_transport { int (*send)(struct mg_transport *, const char *buf, size_t len); int (*recv)(struct mg_transport *, char *buf, size_t len); void (*destroy)(struct mg_transport *); + void (*suspend_until_ready_to_read)(struct mg_transport *); + void (*suspend_until_ready_to_write)(struct mg_transport *); } mg_transport; typedef struct mg_raw_transport { int (*send)(struct mg_transport *, const char *buf, size_t len); int (*recv)(struct mg_transport *, char *buf, size_t len); void (*destroy)(struct mg_transport *); + void (*suspend_until_ready_to_read)(struct mg_transport *); + void (*suspend_until_ready_to_write)(struct mg_transport *); int sockfd; mg_allocator *allocator; } mg_raw_transport; @@ -52,6 +54,8 @@ typedef struct mg_secure_transport { int (*send)(struct mg_transport *, const char *buf, size_t len); int (*recv)(struct mg_transport *, char *buf, size_t len); void (*destroy)(struct mg_transport *); + void (*suspend_until_ready_to_read)(struct mg_transport *); + void (*suspend_until_ready_to_write)(struct mg_transport *); SSL *ssl; BIO *bio; const char *peer_pubkey_type; @@ -66,6 +70,10 @@ int mg_transport_recv(mg_transport *transport, char *buf, size_t len); void mg_transport_destroy(mg_transport *transport); +void mg_transport_suspend_until_ready_to_read(struct mg_transport *); + +void mg_transport_suspend_until_ready_to_write(struct mg_transport *); + int mg_raw_transport_init(int sockfd, mg_raw_transport **transport, mg_allocator *allocator); @@ -75,6 +83,10 @@ int mg_raw_transport_recv(struct mg_transport *, char *buf, size_t len); void mg_raw_transport_destroy(struct mg_transport *); +void mg_raw_transport_suspend_until_ready_to_read(struct mg_transport *); + +void mg_raw_transport_suspend_until_ready_to_write(struct mg_transport *); + #ifndef __EMSCRIPTEN__ // This function is mocked in tests during linking by using --wrap. ON_APPLE // there is no --wrap. An alternative is to use -alias but if a symbol is @@ -84,13 +96,13 @@ MG_ATTRIBUTE_WEAK int mg_secure_transport_init(int sockfd, const char *key_file, mg_secure_transport **transport, mg_allocator *allocator); -#endif int mg_secure_transport_send(mg_transport *, const char *buf, size_t len); int mg_secure_transport_recv(mg_transport *, char *buf, size_t len); void mg_secure_transport_destroy(mg_transport *); +#endif #ifdef __cplusplus } diff --git a/src/mgwasm.c b/src/mgwasm.c index 623b1ab..78ffdea 100644 --- a/src/mgwasm.c +++ b/src/mgwasm.c @@ -1,11 +1,10 @@ #include "mgwasm.h" -#ifdef __EMSCRIPTEN__ - #include -#include #include +#include "emscripten.h" + int read_loop(const int sock) { fd_set fdr; FD_ZERO(&fdr); @@ -24,7 +23,7 @@ int write_loop(const int sock) { fd_set fdw; FD_ZERO(&fdw); FD_SET(sock, &fdw); - int poll = select(sock + 1, NULL, &fdw, NULL, NULL); + const int poll = select(sock + 1, NULL, &fdw, NULL, NULL); if (poll == -1) { return -1; } @@ -36,40 +35,25 @@ int write_loop(const int sock) { static const size_t DELAY_MS = 10; -int mg_yield_until_async_read_sock(const int sock) { +int mg_wasm_suspend_until_ready_to_read(const int sock) { while (1) { - emscripten_sleep(DELAY_MS); - int res = read_loop(sock); - if (res == 1) { - return 1; - } - if (res == -1) { - return -1; + const int res = read_loop(sock); + if (res == 1 || res == -1) { + return res; } + emscripten_sleep(DELAY_MS); } } -int mg_yield_until_async_write_sock(const int sock) { +int mg_wasm_suspend_until_ready_to_write(const int sock) { while (1) { - emscripten_sleep(DELAY_MS); - int res = write_loop(sock); - if (res == 1) { - return 1; + const int res = write_loop(sock); + if (res == 1 || res == -1) { + return res; } if (res == -1) { return -1; } + emscripten_sleep(DELAY_MS); } } - -int mg_yield_until_async_read(const mg_transport *transport) { - int sock = ((mg_raw_transport *)transport)->sockfd; - return mg_yield_until_async_read_sock(sock); -} - -int mg_yield_until_async_write(const mg_transport *transport) { - int sock = ((mg_raw_transport *)transport)->sockfd; - return mg_yield_until_async_write_sock(sock); -} - -#endif diff --git a/src/mgwasm.h b/src/mgwasm.h index 61b4f79..54fdb66 100644 --- a/src/mgwasm.h +++ b/src/mgwasm.h @@ -1,20 +1,7 @@ #ifndef MGCLIENT_MGWASM_H #define MGCLIENT_MGWASM_H -#ifdef __EMSCRIPTEN__ - -#include "emscripten.h" -#include "mgtransport.h" - -int read_loop(int sock); -int write_loop(int sock); - -int mg_yield_until_async_read_sock(int sock); -int mg_yield_until_async_write_sock(int sock); - -int mg_yield_until_async_read(const mg_transport *transport); -int mg_yield_until_async_write(const mg_transport *transport); - -#endif +int mg_wasm_suspend_until_ready_to_read(int sock); +int mg_wasm_suspend_until_ready_to_write(int sock); #endif /* MGCLIENT_MGWASM_H */ From 100e98fbd558b8ff7d76104500146bd520cdcc56 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 15 Mar 2022 14:41:26 +0200 Subject: [PATCH 15/18] added install deps config step in cmake for wasm build --- .github/workflows/ci.yml | 1 - .gitignore | 3 +++ CMakeLists.txt | 3 ++- wasm/install_deps.sh | 6 +++--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09b4417..d87b12b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,7 +141,6 @@ jobs: - name: Build with clang run: | mkdir build - ./wasm/install_deps.sh cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DC_WARNINGS_AS_ERRORS=ON -DWASM=ON make diff --git a/.gitignore b/.gitignore index d8991a0..9a6f85c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ tool/generated/ # Doxygen output files. html/ + +#emsdk folder pulled from wasm/install_deps.sh +wasm/emsdk diff --git a/CMakeLists.txt b/CMakeLists.txt index 05e7990..9741107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,8 @@ cmake_minimum_required(VERSION 3.8) if(WASM) - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/build/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/wasm/install_deps.sh) + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/wasm/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") endif() project(mgclient VERSION 1.2.0) diff --git a/wasm/install_deps.sh b/wasm/install_deps.sh index 3f41cc8..76c948a 100755 --- a/wasm/install_deps.sh +++ b/wasm/install_deps.sh @@ -1,6 +1,6 @@ #!/bin/bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -git clone https://github.com/emscripten-core/emsdk.git ${DIR}/../build/emsdk -${DIR}/../build/emsdk/emsdk install latest -${DIR}/../build/emsdk/emsdk activate latest +git clone https://github.com/emscripten-core/emsdk.git ${DIR}/emsdk +${DIR}/emsdk/emsdk install latest +${DIR}/emsdk/emsdk activate latest From 4c4157208bc82d8491373a906b70c56076ff62f4 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 15 Mar 2022 14:54:05 +0200 Subject: [PATCH 16/18] addressed comments --- include/mgclient.h | 4 +++- src/mgclient.c | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/mgclient.h b/include/mgclient.h index 0a5e1b3..b916a6c 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -15,7 +15,7 @@ #ifndef MGCLIENT_MGCLIENT_H #define MGCLIENT_MGCLIENT_H -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #define MGCLIENT_EXPORT EMSCRIPTEN_KEEPALIVE #include "emscripten.h" #else @@ -1132,7 +1132,9 @@ MGCLIENT_EXPORT void mg_point_3d_destroy(mg_point_3d *point_3d); /// the server. enum mg_sslmode { MG_SSLMODE_DISABLE, ///< Only try a non-SSL connection. +#ifndef __EMSCRIPTEN__ MG_SSLMODE_REQUIRE, ///< Only try a SSL connection. +#endif }; /// An object encapsulating a Bolt session. diff --git a/src/mgclient.c b/src/mgclient.c index f154835..801cd7e 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -29,10 +29,6 @@ #include "mgtransport.h" #include "mgvalue.h" -#ifdef __EMSCRIPTEN__ -#include "mgwasm.h" -#endif - const char *mg_client_version() { return MGCLIENT_VERSION; } int mg_init() { return mg_socket_init(); } From 885f4ffd1420affb6a4f46d1367bb30f2bb4b24c Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 15 Mar 2022 17:16:48 +0200 Subject: [PATCH 17/18] addressed comments --- .gitignore | 2 +- README.md | 7 +++---- src/linux/mgsocket.c | 6 ++++++ src/mgclient.c | 2 -- src/mgsession.c | 3 --- src/mgtransport.c | 2 ++ 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 9a6f85c..7700465 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,5 @@ tool/generated/ # Doxygen output files. html/ -#emsdk folder pulled from wasm/install_deps.sh +# emsdk folder pulled from wasm/install_deps.sh wasm/emsdk diff --git a/README.md b/README.md index 4da2cb7..b0e5dbf 100644 --- a/README.md +++ b/README.md @@ -128,10 +128,9 @@ cmake --build . --target install ``` ## Building WASM (linux only) Compiling `mgclient` for wasm requires the Emscripten sdk. This is automated in the following steps: - 1. wasm/install_deps.sh - 3. mkdir build && cd build - 4. cmake .. -DWASM=ON - 5. make + 1. mkdir build && cd build + 2. cmake .. -DWASM=ON + 3. make Now there should be an `mgclient.js` and an `mgclient.wasm` found in `mgclient/build/` ## Using the library diff --git a/src/linux/mgsocket.c b/src/linux/mgsocket.c index eb42f84..d7ba7db 100644 --- a/src/linux/mgsocket.c +++ b/src/linux/mgsocket.c @@ -94,6 +94,11 @@ int mg_socket_connect_handle_error(int *sock, int status, mg_session *session) { } int mg_socket_options(int sock, mg_session *session) { +#ifdef __EMSCRIPTEN__ + (void)sock; + (void)session; + return MG_SUCCESS; +#else struct { int level; int optname; @@ -125,6 +130,7 @@ int mg_socket_options(int sock, mg_session *session) { } } return MG_SUCCESS; +#endif } ssize_t mg_socket_send(int sock, const void *buf, int len) { diff --git a/src/mgclient.c b/src/mgclient.c index 801cd7e..6e8c721 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -478,12 +478,10 @@ static int init_tcp_connection(const mg_session_params *params, int *sockfd, return status; } -#ifndef __EMSCRIPTEN__ int set_options_status = mg_socket_options(tsockfd, session); if (set_options_status != MG_SUCCESS) { return set_options_status; } -#endif *sockfd = tsockfd; return 0; diff --git a/src/mgsession.c b/src/mgsession.c index a50bd57..f2043e7 100644 --- a/src/mgsession.c +++ b/src/mgsession.c @@ -28,9 +28,6 @@ #include "mgconstants.h" #include "mgsession.h" #include "mgtransport.h" -#ifdef __EMSCRIPTEN__ -#include "mgwasm.h" -#endif int mg_session_status(const mg_session *session) { if (!session) { diff --git a/src/mgtransport.c b/src/mgtransport.c index 3982d24..03980af 100644 --- a/src/mgtransport.c +++ b/src/mgtransport.c @@ -28,7 +28,9 @@ #include "mgclient.h" #include "mgcommon.h" #include "mgsocket.h" +#ifdef __EMSCRIPTEN__ #include "mgwasm.h" +#endif int mg_init_ssl = 1; From 3ca091704adc7e6fd729c6f252fcb6c29878d373 Mon Sep 17 00:00:00 2001 From: Kostas Date: Tue, 15 Mar 2022 17:31:28 +0200 Subject: [PATCH 18/18] fix client ub in tests/client.cpp --- tests/client.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/client.cpp b/tests/client.cpp index 997127e..9cdc813 100644 --- a/tests/client.cpp +++ b/tests/client.cpp @@ -12,18 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include +#include + #include #include #include -#include -#include - #include "mgclient.h" #include "mgcommon.h" #include "mgsession.h" #include "mgsocket.h" - #include "test-common.hpp" using namespace std::string_literals; @@ -70,6 +69,8 @@ struct test_transport { int (*send)(struct mg_transport *, const char *buf, size_t len); int (*recv)(struct mg_transport *, char *buf, size_t len); void (*destroy)(struct mg_transport *); + void (*suspend_until_ready_to_read)(struct mg_transport *); + void (*suspend_until_ready_to_write)(struct mg_transport *); union { struct { SSL *ssl; @@ -98,6 +99,8 @@ int __wrap_mg_secure_transport_init(int sockfd, const char *cert, ttransport->send = mg_raw_transport_send; ttransport->recv = mg_raw_transport_recv; ttransport->destroy = test_transport_destroy; + ttransport->suspend_until_ready_to_read = NULL; + ttransport->suspend_until_ready_to_write = NULL; ttransport->peer_pubkey_type = "rsaEncryption"; ttransport->peer_pubkey_fp = TEST_KEY_FP; *transport = (mg_secure_transport *)ttransport;