diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2021-09-21 23:05:01 +0200 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2021-09-21 23:05:01 +0200 |
commit | 47da9bbedc7b30202fda404880a4d8762fcaf8ce (patch) | |
tree | b2975506a46b733e12ca0320d66313bcd80d40f0 /src/h.c | |
parent | untested, compiles (diff) | |
download | discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar.gz discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar.bz2 discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar.lz discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar.xz discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.tar.zst discord.c-47da9bbedc7b30202fda404880a4d8762fcaf8ce.zip |
Diffstat (limited to 'src/h.c')
-rw-r--r-- | src/h.c | 116 |
1 files changed, 63 insertions, 53 deletions
@@ -44,6 +44,7 @@ enum dc_status { /* theese are flags and should be and-checked */ DC_NO_WRITE = 1 << 21, /* signaling dc_ws_stack not to call lws_callback_on_writeable */ DC_SET_WS_ACTIVE = 1 << 22, /* whether _CREATE _cb shall set client->status =| DC_WS_ACTIVE */ 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_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! */ enum dc_permissions { /* other permissions exist, but are not implemented/understood */ @@ -131,7 +132,11 @@ struct dc_api_io { /* output struct does NOT contain void * data (user pointer) }; #define DC_API_IO_MEMB_GC(m, t) if (m && m->status & DC_IN_PROGRESS) { \ t##_free(m, DC_UNSET); \ - m = NULL; } + m = NULL; } \ + if (m && m->status & DC_EXPLICIT_NULL) { \ + m->status &= ~DC_EXPLICIT_NULL; \ + m = NULL; \ + } #define DC_API_IO_GC(s) do { /* this is called if: json_cb will start parsing another before callback, */ \ DC_API_IO_MEMB_GC(s.message, dc_message); /* WS connection closed, meaning json_cb */ \ DC_API_IO_MEMB_GC(s.channel, dc_channel); /* will never be called again */ \ @@ -174,17 +179,15 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c DC_JSON_ME_USERNAME, /* note: _ME is client->user ONLY for first d.user object. subsequent */ DC_JSON_ME_ID, /* packets may contain user objects as well, they are other users */ DC_JSON_ME_DISCRIMINATOR, - DC_JSON_FRIEND, - DC_JSON_FRIEND_ID, - DC_JSON_FRIEND_USERNAME, - DC_JSON_FRIEND_DISCRIMINATOR, + DC_JSON_FRIEND, /* this is the id */ + DC_JSON_USER, /* list of users at first connect */ + DC_JSON_USER_ID, + DC_JSON_USER_NAME, + DC_JSON_USER_DISCRIMINATOR, DC_JSON_DM, DC_JSON_DM_TYPE, DC_JSON_DM_ID, - DC_JSON_DM_USER, - DC_JSON_DM_USER_NAME, - DC_JSON_DM_USER_ID, - DC_JSON_DM_USER_DISCRIMINATOR, + DC_JSON_DM_USER, /* this is the ID */ DC_JSON_GUILD, DC_JSON_GUILD_NAME, DC_JSON_GUILD_ID, @@ -253,21 +256,19 @@ char * dc_json_paths[] = { /* array of paths we are interested in */ "s", "t", "d.heartbeat_interval", - "d.user", /* NOTE: presence updates have same format, so only set own user once */ + "d.user", "d.user.username", "d.user.id", "d.user.discriminator", - "d.relationships[].user", - "d.relationships[].user.id", - "d.relationships[].user.username", - "d.relationships[].user.discriminator", + "d.relationships[].id", + "d.users[]", + "d.users[].id", + "d.users[].username", + "d.users[].discriminator", "d.private_channels[]", "d.private_channels[].type", "d.private_channels[].id", - "d.private_channels[].recipients[]", - "d.private_channels[].recipients[].username", - "d.private_channels[].recipients[].id", - "d.private_channels[].recipients[].discriminator", + "d.private_channels[].recipients_ids[]", "d.guilds[]", "d.guilds[].name", "d.guilds[].id", @@ -357,7 +358,10 @@ struct dc_payload * dc_payload_init () { return s; } void dc_payload_free (struct dc_payload * s, enum dc_status t) { - free(s->body-LWS_PRE); + if (!s) + return; + if (s->body) + free(s->body-LWS_PRE); if (!(t & DC_REPLACE)) free(s); return; @@ -366,9 +370,9 @@ void dc_payload_free (struct dc_payload * s, enum dc_status t) { #define DC_ISAS_INIT(type/* w/o struct */, name) do { name##_sizeof = DC_ALLOC_CHUNK; /* structs ISA */ \ name = calloc(name##_sizeof, sizeof(struct type *)); } while (0) /* prep arr, NO INIT membrs */ #define DC_ISASIQ(shortname) DC_ISAS_INIT(dc_##shortname, s->shortname##s) /* ISAS init quick */ -#define DC_ISAF(shortname) for (size_t i = 0; i < s->shortname##s_sizeof; i++) /* ISA free */ \ - dc_##shortname##_free(s->shortname##s[i], DC_UNSET); \ - free(s->shortname##s); /* no problem if we free past _lenght, as uninited are NULL */ +#define DC_ISAF(shortname) for (size_t i = 0; i < s->shortname##s_sizeof; i++) /* hmm, I used to fre */ \ + dc_##shortname##_free(s->shortname##s[i], DC_UNSET); /* till _sizeof, but now I fixd */ \ + free(s->shortname##s); /* to only free till _length. is this problematic in any ways? */ struct dc_client { DC_STRUCT_PREFIX char * authorization; /* yesfree - authorization header value */ @@ -385,11 +389,42 @@ struct dc_client { DC_ISASQ(guild); /* yesfree array of pointers only - guilds of this user */ DC_ISASQ(user); /* yesfree array of pointers only - friends of this user */ }; +struct dc_guild { + DC_STRUCT_PREFIX + char * name; /* yesfree */ + unsigned long long int id; /* 0 for virtual DMs guild */ + struct dc_client * client; /* nofree */ + struct dc_channel * channel; /* nofree - first channel */ + struct dc_role * role; /* nofree - first role. NOTE: role->id == guild->id => @everyone role */ + enum dc_permissions permissions; + enum dc_status status; +#ifdef DC_UI_GTK + GtkTreeIter iter; /* NOTE: only works when GtkTreeModel has a flag GTK_TREE_MODEL_ITERS_PERSIST; see paragraph 8 of description of file:///usr/share/doc/libgtk-3-doc/gtk3/GtkTreeModel.html */ + gboolean is_iter; + /* GtkTreeRowReference * row; */ /* yesfree - indicating the row */ /* not used: IRC message: "00:51:29 @Company | also: Don't create too many tree row references, those things are slow" */ +#endif +}; +struct dc_guild * dc_guild_init () { + struct dc_guild * s = calloc(1, sizeof(*s)); + return s; +} +void dc_guild_free (struct dc_guild * s, enum dc_status t) { + if (!s) + return; + free(s->name); + if (!(t & DC_REPLACE)) /* we do this because we want to keep the pointer intact sometimes and */ + free(s); /* reused; for example when replacing/updating structs */ +} struct dc_client * dc_client_init () { struct dc_client * s = calloc(1, sizeof(*s)); DC_ISASIQ(payload); DC_ISASIQ(guild); DC_ISASIQ(user); + DC_MR(s->guilds); /* direct messages virtual guild is not in program, to prevent confusion */ + s->guilds_length = 1; /* because of duplicated 0 id value; freeing is therefore done from */ + s->guilds[0] = dc_guild_init(); /* dc_client_free */ + s->guilds[0]->name = strdup("Direct messages"); /* TODO: use gettext or similar for t9ns */ + s->guilds[0]->client = s; return s; } void dc_client_free (struct dc_client * s, enum dc_status t) { @@ -399,6 +434,7 @@ void dc_client_free (struct dc_client * s, enum dc_status t) { free(s->email); free(s->password); DC_ISAF(payload); + dc_guild_free(s->guilds[0], DC_UNSET); /* see dc_client_init for explanation */ free(s->guilds); free(s->users); if (!(t & DC_REPLACE)) @@ -415,32 +451,6 @@ void dc_ws_stack(struct dc_client * c, struct dc_payload * p, enum dc_status s) lws_callback_on_writable(c->pass->wsi); return; } -struct dc_guild { - DC_STRUCT_PREFIX - char * name; /* yesfree */ - unsigned long long int id; /* 0 for virtual DMs guild */ - struct dc_client * client; /* nofree */ - struct dc_channel * channel; /* nofree - first channel */ - struct dc_role * role; /* nofree - first role. NOTE: role->id == guild->id => @everyone role */ - enum dc_permissions permissions; - enum dc_status status; -#ifdef DC_UI_GTK - GtkTreeIter iter; /* NOTE: only works when GtkTreeModel has a flag GTK_TREE_MODEL_ITERS_PERSIST; see paragraph 8 of description of file:///usr/share/doc/libgtk-3-doc/gtk3/GtkTreeModel.html */ - gboolean is_iter; - /* GtkTreeRowReference * row; */ /* yesfree - indicating the row */ /* not used: IRC message: "00:51:29 @Company | also: Don't create too many tree row references, those things are slow" */ -#endif -}; -struct dc_guild * dc_guild_init () { - struct dc_guild * s = calloc(1, sizeof(*s)); - return s; -} -void dc_guild_free (struct dc_guild * s, enum dc_status t) { - if (!s) - return; - free(s->name); - if (!(t & DC_REPLACE)) /* we do this because we want to keep the pointer intact sometimes and */ - free(s); /* reused; for example when replacing/updating structs */ -} struct dc_channel { DC_STRUCT_PREFIX char * name; /* yesfree - name */ @@ -677,8 +687,9 @@ struct dc_program * dc_program_init () { } void dc_program_free (struct dc_program * s, enum dc_status t) { if (!s) - return; - DC_ISAF(client); + return; /* \/ call first because _cb is called several times during destroy ,,, */ + lws_context_destroy(s->lws_context); /* closes all connections and destroys all wsis */ + DC_ISAF(client); /* /\ ,,, and callback handlers (_CLOSED, _DESTROY) may do stuff with memory. */ DC_ISAF(guild); DC_ISAF(channel); DC_ISAF(message); @@ -688,7 +699,6 @@ void dc_program_free (struct dc_program * s, enum dc_status t) { DC_ISAF(permission); DC_ISAF(attached_function); DC_ISAF(api_io); - lws_context_destroy(s->lws_context); /* closes all connections and destroys all wsis */ if (!(t & DC_REPLACE)) free(s); } @@ -715,6 +725,7 @@ void dc_api_stack (struct dc_api_io); #define DC_ADD_X(x) struct dc_##x * dc_add_##x (struct dc_##x *** p, size_t * so, size_t * l, struct dc_##x * u, enum dc_status s) { \ struct dc_##x * us; \ if ((us = dc_find_##x(*p, *l, u->id))) { \ + fprintf(stderr, "debug: %s found already existing member\n", __func__); \ if (us == u) \ return us; \ if (s & DC_REPLACE) { \ @@ -726,15 +737,14 @@ void dc_api_stack (struct dc_api_io); } \ if (s & DC_MAY_FREE) { \ dc_##x##_free(u, DC_UNSET); \ - fprintf(stderr, "debug: %s freed already existing member\n", __func__); \ } \ return us; \ } \ if (*so <= *l) { \ *so = ceil(*so*DC_REALLOC_K); \ *p = realloc(*p, sizeof(**p) * *so); \ - fprintf(stderr, "debug: %s resized ISA\n", __func__); \ } \ + fprintf(stderr, "debug: %s inserted into ISA\n", __func__); \ (*p)[(*l)++] = u; \ return u; \ } |