From 7877e512c2f228e0e98340d30cfee44e14c29cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Sat, 25 Sep 2021 18:29:34 +0200 Subject: fixed roles --- Makefile | 3 --- README.md | 34 +++++++++------------------------- src/api.c | 11 ++++++++++- src/h.c | 28 ++++++++++++++++------------ 4 files changed, 35 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index 8bc8aa4..8f2b580 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,3 @@ gensupp: cc misc/valgrind-supp-extractor.c -otmp/vse G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind $(VGARGS) --gen-suppressions=all ./discord.c tmp/vse < valgrind-out.txt > tmp/gend.supp - -echo: - echo $$DC_E diff --git a/README.md b/README.md index 8721154..5ea70a4 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ sudo apt install discord.c you need to add [my apt repository](https://prog.sijanec.eu/). -built packages only exist for `amd64`, `arm64` and `i386`. for other architectures grab the source package: +built packages only exist for `amd64`, `arm64` and `i386` (`i686`). for other architectures grab the source package: ``` apt-get --install build discord.c @@ -79,28 +79,12 @@ completing this task would make `discord.c` the first and the only alternative c it would be useful to have an android port, and luckily this is possible with little effort due to the GTK broadway backend that interfaces with a HTML renderer, WebView for example. - +* use an `i386` compatible machine with `debian` `bullseye` (I use a Dell Latitude D620) +* debugging with valgrind: `make valgrind-prepare` once and `make valgrind` for profiling `./discord.c` +* generating valgrind suppressions: `make gensupp`, running `make valgrind` afterwards will ignore all +* `make cc` to compile code under `gcc`, `tcc` and `clang` +* optimization is always 0, binaries always have debug symbols +* `make -e CC=gcc` to choose a compiler instead of `cc`. +* `make -e CC="clang -fsanitize=address" && ASAN_OPTIONS=detect_leaks=1` to use `clang` leak checker diff --git a/src/api.c b/src/api.c index c405cff..7171e3a 100644 --- a/src/api.c +++ b/src/api.c @@ -238,7 +238,11 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn role = &pass->api_io.guild->role; while (*role) role = &(*role)->next; - *role = pass->api_io.guild->role; + if (!dc_find_ll_role(pass->api_io.guild->role, pass->api_io.role->id)) { + fprintf(stderr, "new role id=%lld (:\n", pass->api_io.role->id); + pass->api_io.role->next = NULL; + *role = pass->api_io.role; + } pass->api_io.role->guild = pass->api_io.guild; if (pass->api_io.role->name && !strncmp(pass->api_io.role->name, "@everyone", strlen(pass->api_io.role->name))) pass->api_io.role->status |= DC_EVERYONE; @@ -681,6 +685,11 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun } } struct dc_api_io dc_api_o (struct dc_api_io i /* for ->program */) { + if (!i.program) { + i.type = DC_API_STATUS; + i.status = DC_USER_ERROR; + return i; + } if (i.program->lws_context) lws_service(i.program->lws_context, 0); for (size_t x = 0; x < i.program->clients_length; x++) { diff --git a/src/h.c b/src/h.c index bd20bf8..df7907f 100644 --- a/src/h.c +++ b/src/h.c @@ -51,6 +51,7 @@ enum dc_status { /* theese are flags and should be and-checked */ DC_REPLACE = 1 << 23, /* dc_add_x replace old with new on found, _free: only free members */ DC_EXPLICIT_NULL = 1 << 24, /* MEMB_GC will NULL this member (PROGRES?aftr free) (& clear bit) */ DC_EVERYONE = 1 << 25, /* role applies to all guild users */ + DC_USER_ERROR = 1 << 26, /* lib user made an error, passed NULL pointer to _o for example */ DC_INTERNAL = DC_FROM_LWS | DC_FROM_API, /* call originates from an internal function */ }; /* note: when checking status, first check for DC_OK, if it's set then disregard errors! */ #define DC_ADMIN (1 << 3) /* not all enum fields are implemented/understood */ @@ -108,7 +109,7 @@ enum dc_api_io_type { DC_API_REGISTER,/* i: pass a dc_client, to relogin FIX pr rt cl&cl->user not creat new */ /* o: the previously passed dc_client with set status */ DC_API_STATUS, /* i: N/A */ - /* o: new status message, pointer to internal string - tr0 */ + /* o: check ->status */ DC_API_USER, /* i: query for user by id, pass dc_user-tr1 */ /* o: prev passed dc_user but filled (or not: ->status may indicate error) */ DC_API_ROLE, /* i: query for role by id, pass dc_role-tr1 */ @@ -665,6 +666,18 @@ enum dc_status dc_handle_ping (struct dc_api_io io, void * userdata) { /* tries } struct dc_program * dc_program_init () { struct dc_program * s = calloc(1, sizeof(struct dc_program)); + /* lws init, it may fail so we first do this to return NULL without memleak (thanks, clang) */ + struct lws_context_creation_info info; + memset(&info, 0, sizeof(info)); + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we are not listening - we are a client */ + info.protocols = dc_lws_protocols; + info.fd_limit_per_thread = DC_LWS_MAX_FD; + if (!(s->lws_context = lws_create_context(&info))) { + lwsl_err("lws init failed\n"); + free(s); + return NULL; /* of course our UI does not check for failure of init function, so the */ + } /* program will just crash, but I assume lws init will never fail (correct me if I'm wrong) */ DC_ISASIQ(client); DC_ISASIQ(guild); DC_ISASIQ(channel); @@ -674,17 +687,6 @@ struct dc_program * dc_program_init () { DC_ISASIQ(permission); DC_ISASIQ(attached_function); DC_ISASIQ(api_io); - /* lws init */ - struct lws_context_creation_info info; - memset(&info, 0, sizeof(info)); - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; /* we are not listening - we are a client */ - info.protocols = dc_lws_protocols; - info.fd_limit_per_thread = DC_LWS_MAX_FD; - if (!(s->lws_context = lws_create_context(&info))) { - lwsl_err("lws init failed\n"); - return NULL; - } struct dc_api_io io; /* attach a function for pinging wss of every client */ memset(&io, 0, sizeof(io)); io.type = DC_API_ATTACH; @@ -780,6 +782,7 @@ DC_GEN_X(channel, CHANNEL) DC_FIND_LL_X(channel) DC_GEN_X(guild, GUILD) DC_GEN_X(role, ROLE) +DC_FIND_LL_X(role) #define DC_ISAE(a) &(a), &(a##_sizeof), &(a##_length) /* ISA Expand */ #define DC_ISAN NULL, NULL, NULL /* ISA NULL */ #define DC_TRANSFER_CHANNEL(n, o) do { /* n is going to DC_REPLACE o, transfer important data */ \ @@ -799,6 +802,7 @@ DC_GEN_X(role, ROLE) void dc_transfer_role (struct dc_role * n, struct dc_role * o) { n->next = o->next; if (!n->users_length) { /* if we didn't update users array in the new role object */ + free(n->users); /* thanks, clang, we have to free pointer array before overwriting it! */ n->users = o->users; n->users_sizeof = o->users_sizeof; n->users_length = o->users_sizeof; -- cgit v1.2.3