diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2021-09-18 21:33:34 +0200 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2021-09-18 21:33:34 +0200 |
commit | 93a241fc7d93aad6ad26857472d80ec58adae3d8 (patch) | |
tree | a499822c015bfe82bfd9cc18ca6a8ed6cc0bc624 /src/h.c | |
parent | wow, this is really going somewhere (diff) | |
download | discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar.gz discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar.bz2 discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar.lz discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar.xz discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.tar.zst discord.c-93a241fc7d93aad6ad26857472d80ec58adae3d8.zip |
Diffstat (limited to '')
-rw-r--r-- | src/h.c | 108 |
1 files changed, 98 insertions, 10 deletions
@@ -39,6 +39,8 @@ enum dc_status { /* theese are flags and should be and-checked */ DC_SET_PASS = 1 << 16, /* whether _CREATE _cb shall set client->passs. api sets on _WS create */ DC_IN_PROGRESS = 1 << 17, /* object is in parsing (by json_cb) */ DC_DESTROY_CB = 1 << 18, /* wether cb shall call api on DESTROY (used for http responses) */ + DC_MAY_FREE = 1 << 19, /* whether dc_*_add() shall free passed in pointer if found one in ISA */ + DC_WS_ACTIVE = 1 << 20, /* set at API_WS so that api_o will reconnect WS if connection dropps */ 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 */ @@ -158,8 +160,17 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c DC_JSON_S, /* packet sequence number */ DC_JSON_PING, /* interval */ DC_JSON_ME, /* never useful in path parser, but startswith() checks if we're in object */ + DC_JSON_ME_USERNAME, + DC_JSON_ME_ID, + DC_JSON_ME_DISCRIMINATOR, DC_JSON_FRIEND, /* never useful in path parser, but startswith() checks if we're in object */ DC_JSON_DM, /* never useful in path parser, but startswith() checks if we're in object */ + DC_JSON_DM_TYPE, + DC_JSON_DM_ID, + DC_JSON_DM_USER, /* never useful in path parser, but startswith() checks if we're in object */ + DC_JSON_DM_USER_NAME, + DC_JSON_DM_USER_ID, + DC_JSON_DM_USER_DISCRIMINATOR, DC_JSON_PATHS_LENGTH }; char * dc_json_paths[] = { /* array of paths we are interested in */ @@ -167,8 +178,17 @@ char * dc_json_paths[] = { /* array of paths we are interested in */ "s", "d.heartbeat_interval", "d.user", /* NOTE: presence updates have same format, so only set own user once */ + "d.user.username", + "d.user.id", + "d.user.discriminator", "d.relationships[].user", - "d.private_channels[]" + "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" }; struct dc_lws_pass { /* struct that is allocated for in dc_lws_cb unique per connection in void * us */ DC_STRUCT_PREFIX @@ -214,17 +234,20 @@ struct dc_client { char * email; /* yesfree */ char * password; /* yesfree */ struct dc_user * user; /* nofree - logged in user */ - struct dc_guild * guild; /* nofree - first guild */ enum dc_status status; struct dc_lws_pass * pass; /* pass of ws. _cb sets it on CREATE and NULLs on DESTROY */ unsigned long long int last_packet; /* last packet sequence number for ping */ time_t ping_interval; time_t last_ping; - DC_ISASQ(payload); /* array of payloads we must send over ws */ + DC_ISASQ(payload); /* yesfree - array of payloads we must send over ws */ + 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_client * dc_client_init () { struct dc_client * s = calloc(1, sizeof(*s)); DC_ISASIQ(payload); + DC_ISASIQ(guild); + DC_ISASIQ(user); return s; } void dc_client_free (struct dc_client * s) { @@ -234,6 +257,8 @@ void dc_client_free (struct dc_client * s) { free(s->email); free(s->password); DC_ISAF(payload); + free(s->guilds); + free(s->users); free(s); } void dc_ws_stack(struct dc_client * c, struct dc_payload * p) { /* we could just use pass->body and */ @@ -249,12 +274,10 @@ void dc_ws_stack(struct dc_client * c, struct dc_payload * p) { /* we could just struct dc_guild { DC_STRUCT_PREFIX char * name; /* yesfree */ - char * alternative_messages_url; /* yesfree, internal - for virtual DMs guild */ unsigned long long int id; /* 0 for virtual DMs guild */ struct dc_client * client; /* nofree */ - struct dc_guild * next; /* nofree - next guild (linked list of all guilds of dc_client) */ struct dc_channel * channel; /* nofree - first channel */ - struct dc_role * role; /* nofree - first role. NOTE: first role is always role with role ID that is same as guild ID and it is the @everyone role */ + struct dc_role * role; /* nofree - first role. NOTE: 1. role->id == guild->id (@everyone role) */ enum dc_permissions permissions; enum dc_status status; #ifdef DC_UI_GTK @@ -271,7 +294,6 @@ void dc_guild_free (struct dc_guild * s) { if (!s) return; free(s->name); - free(s->alternative_messages_url); free(s); } struct dc_channel { @@ -285,6 +307,7 @@ struct dc_channel { struct dc_message * message; /* nofree - first message (ordered by time) */ struct dc_permission * permission; /* nofree - first permission */ enum dc_status status; + DC_ISASQ(user); /* yesfree array only - participants in DM channels */ #ifdef DC_UI_GTK GtkTreeIter iter; /* see notes of struct dc_guild */ gboolean is_iter; /* XXX use this with caution: only if it's possible for treemodels to contains orphans, this works. otherwise, parents will be removed first and then channels will not het their is_iters invalidated. guild's is_iter will always get invalidated. file:///usr/share/doc/libgtk-3-doc/gtk3/GtkTreeStore.html#gtk-tree-store-iter-is-valid could be a solution but it's said to be slow. */ @@ -292,6 +315,7 @@ struct dc_channel { }; struct dc_channel * dc_channel_init () { struct dc_channel * s = calloc(1, sizeof(*s)); + DC_ISASIQ(user); return s; } void dc_channel_free (struct dc_channel * s) { @@ -299,6 +323,7 @@ void dc_channel_free (struct dc_channel * s) { return; free(s->name); free(s->topic); + free(s->users); free(s); } struct dc_message { @@ -366,8 +391,6 @@ struct dc_user { unsigned long long int id; short int discriminator; enum dc_status status; - char * path; /* yesfree, internal, so parser knows what object this user is from */ - struct dc_user * next; /* nofree, next friend in ll of friends, first is client->user->next */ }; struct dc_user * dc_user_init () { struct dc_user * s = calloc(1, sizeof(*s)); @@ -377,7 +400,6 @@ void dc_user_free (struct dc_user * s) { if (!s) return; free(s->username); - free(s->path); free(s); } struct dc_permission { /* permissions can be individual on a per-channel basis */ @@ -417,6 +439,13 @@ void dc_attached_function_free (struct dc_attached_function * s) { return; free(s); } +void dc_lws_pass_free (struct dc_lws_pass * s) { + if (!s) + return; + free(s->body); + DC_API_IO_GC(s->api_io); + free(s); +} static int dc_lws_cb (struct lws *, enum lws_callback_reasons, void *, void *, size_t); static const struct lws_protocols dc_lws_protocols[] = { {"dc", dc_lws_cb, /* sizeof(struct dc_lws_pass) */ 0 /* lws naj NE ALOCIRA */, DC_LWS_MAX_RX, 0, NULL, 0}, @@ -509,3 +538,62 @@ void dc_program_free (struct dc_program * s) { lws_context_destroy(s->lws_context); /* closes all connections and destroys all wsis */ free(s); } +void dc_api_stack (struct dc_api_io); +#define DC_FIND_X(x) struct dc_##x * dc_find_##x(struct dc_##x ** p, size_t l, unsigned long long int id) { \ + for (size_t i = 0; i < l; i++) \ + if (p[i]->id == id) { \ + fprintf(stderr, "id %llu was found!\n", id); \ + return p[i]; \ + } \ + return NULL; \ +} +#define DC_FIND_LL_X(x) struct dc_##x * dc_find_ll_##x(struct dc_##x * u, unsigned long long int id) { \ + struct dc_##x ** z = &u; \ + if (!u) \ + return NULL; \ + while (*z) { \ + if ((*z)->id == id) \ + return *z; \ + z = &(*z)->next; \ + } \ + return NULL; \ +} /* untested, not sure if works!!! */ +#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))) { \ + if (s & DC_MAY_FREE) { \ + dc_##x##_free(u); \ + 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__); \ + } \ + (*p)[(*l)++] = u; \ + return u; \ +} +#define DC_ADDR_X(x, y) struct dc_##x * dc_addr_##x (struct dc_program * p, struct dc_##x *** a, size_t * so, size_t * l, struct dc_##x * u, enum dc_status s) { \ + struct dc_##x * us; \ + if (!a) { \ + if (u == (us = dc_add_##x(&p->x##s, &p->x##s_sizeof, &p->x##s_length, u, s))) \ + return us; \ + } else \ + if (u == (us = dc_add_##x(a, so, l, u, s))) \ + return us; \ + struct dc_api_io io; \ + memset(&io, 0, sizeof(io)); \ + io.type = DC_API_##y; \ + io.program = p; \ + io.x = u; \ + dc_api_stack(io); \ + return u; \ +} /* add with report */ +#define DC_GEN_X(x, y) DC_FIND_X(x) DC_ADD_X(x) DC_ADDR_X(x, y) +DC_GEN_X(user, USER) +DC_GEN_X(channel, CHANNEL) +DC_FIND_LL_X(channel) +#define DC_ISAE(a) &a, &a##_sizeof, &a##_length /* ISA Expand */ +#define DC_ISAN NULL, NULL, NULL /* ISA NULL */ |