summaryrefslogtreecommitdiffstats
path: root/src/h.c
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2021-09-21 23:05:01 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2021-09-21 23:05:01 +0200
commit47da9bbedc7b30202fda404880a4d8762fcaf8ce (patch)
treeb2975506a46b733e12ca0320d66313bcd80d40f0 /src/h.c
parentuntested, compiles (diff)
downloaddiscord.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.c116
1 files changed, 63 insertions, 53 deletions
diff --git a/src/h.c b/src/h.c
index e090c96..1a0988b 100644
--- a/src/h.c
+++ b/src/h.c
@@ -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; \
}