summaryrefslogtreecommitdiffstats
path: root/src/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c179
1 files changed, 91 insertions, 88 deletions
diff --git a/src/api.c b/src/api.c
index 20d7b4f..c8b44bc 100644
--- a/src/api.c
+++ b/src/api.c
@@ -25,11 +25,12 @@ void dc_api_stack (struct dc_api_io i) { /* stack output struct to be delivered
*(i.program->api_ios[i.program->api_ios_length++]) = i;
return;
}
-signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ reason) {
+signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warnings of incompatible pointer times, we create a new type with enum later on */
enum dc_json_paths path = ctx->path_match-1; /* we assume that the order of incoming data is */
struct dc_lws_pass * pass = ctx->user; /* correct. op and t should come first, etc. */
struct dc_client * client = pass->api_io.client;
struct dc_program * program = pass->api_io.program;
+ struct dc_user * user; /* don't confuse this with client->user, this is just a var for you use */
pass->json_reason = reason;
if (reason == LEJPCB_FAILED || reason == LEJPCB_COMPLETE || reason == LEJPCB_START) {
if (pass->parsing_status)
@@ -39,7 +40,8 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
pass->parsing_status = NULL;
return '\0';
}
- fprintf(stderr, "JSON: %s %s\n", ctx->path, ctx->buf);
+ if (getenv("DC_J")) /* print json to standard error */
+ fprintf(stderr, "JSON: %s %s\n", ctx->path, ctx->buf);
if (ctx->path_match && reason & LEJP_FLAG_CB_IS_VALUE) {
switch (path) {
case DC_JSON_S: /* packet sequence number */
@@ -69,10 +71,10 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
default: /* to prevent warning: enumeration value DC_JSON_* not handled */
break;
}
- return '\0';
}
- if (startswith(ctx->path, dc_json_paths[DC_JSON_ME]) && reason & LEJP_FLAG_CB_IS_VALUE
- && (!client->user || !client->user->username || !client->user->id || client->user->status & DC_INCOMPLETE)) { /* if filled, then it's someone else */
+ if (reason & LEJP_FLAG_CB_IS_VALUE && (path == DC_JSON_ME_USERNAME || path == DC_JSON_ME_ID || path == DC_JSON_ME_DISCRIMINATOR) && (!client->user || !client->user->username || !client->user->id || client->user->status & DC_INCOMPLETE)) { /* if filled, then it's someone else */
+ if (getenv("DC_R")) /* detect user parser */
+ raise(SIGINT);
if (!client->user) { /* on first d.user this is our user, subsequent are someone else! */
DC_MR(program->users); /* don't need DC_IN_PROGRESS, we have ref in cl */
program->users[program->users_length++] = client->user = dc_user_init();
@@ -89,6 +91,8 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
if (client->user->status & DC_INCOMPLETE) { /* we can't just check if */
client->user->discriminator = atoi(ctx->buf); /* !discriminat, */
client->user->status &= ~DC_INCOMPLETE; /* because 0 is allowd */
+ if (getenv("DC_C"))
+ dc_interrupted++;
}
break;
default:
@@ -96,64 +100,32 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
}
return '\0'; /* because we use same checks for parsing other users GUILD_MEMBER_UPDATE */
}
- if (startswith(ctx->path, dc_json_paths[DC_JSON_FRIEND]) || startswith(ctx->path, dc_json_paths[DC_JSON_ME])) {
- if ((path == DC_JSON_FRIEND || path == DC_JSON_ME) && reason == LEJPCB_OBJECT_START) {
- /* dc_user_free(pass->api_io.user); */ /* parser branches MUST ALWAYS set to 0 */
- pass->api_io.user = dc_user_init(); /* and possibly free api_io members after! */
- pass->api_io.user->status |= DC_IN_PROGRESS; /* if we never get here again */
- }
- if (path == DC_JSON_FRIEND && reason == LEJPCB_OBJECT_END) { /* if that's a friend */
- pass->api_io.user = dc_addr_user(program, DC_ISAE(program->users), pass->api_io.user, DC_MAY_FREE);
- if (!dc_find_user(client->users, client->users_length, pass->api_io.user->id)) {
- fprintf(stderr, "got a new friend (: %s#%d %llu\n", pass->api_io.user->username ? pass->api_io.user->username : "NULL", pass->api_io.user->discriminator, pass->api_io.user->id);
- pass->api_io.user = dc_add_user(DC_ISAE(client->users), pass->api_io.user, DC_UNSET); /* already reported, already inserted in program, nof */
- pass->api_io.user->status &= ~(DC_IN_PROGRESS);
- }
- pass->api_io.user = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
- }
- if (path == DC_JSON_ME && reason == LEJPCB_OBJECT_END) { /* if it was just a user */
- pass->api_io.user = dc_addr_user(program, DC_ISAE(program->users), pass->api_io.user, DC_MAY_FREE);
- pass->api_io.user = NULL;
- }
- if (reason & LEJP_FLAG_CB_IS_VALUE && pass->api_io.user)
- switch(path) {
- case DC_JSON_FRIEND_USERNAME:
- if (!pass->api_io.user->username) /* yup, we don't trust serv */
- pass->api_io.user->username = strdup(ctx->buf);
- break;
- case DC_JSON_FRIEND_ID:
- pass->api_io.user->id = strtoll(ctx->buf, NULL, 10);
- break;
- case DC_JSON_FRIEND_DISCRIMINATOR:
- pass->api_io.user->discriminator = atoi(ctx->buf);
- break; /* yeah, we don't care about nicknames */
- default:
- break;
- }
+ if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER) && reason == LEJPCB_OBJECT_START) { /* user parsing start */
+ /* dc_user_free(pass->api_io.user); */ /* parser branches MUST ALWAYS set to 0 */
+ pass->api_io.user = dc_user_init(); /* and possibly free api_io members after! */
+ pass->api_io.user->status |= DC_IN_PROGRESS; /* if we never get here again */
}
- if (startswith(ctx->path, dc_json_paths[DC_JSON_DM])) {
- if (!client->guilds_length) {
- DC_MR(program->guilds);
- DC_MR(client->guilds);
- program->guilds[program->guilds_length++] = client->guilds[0] = dc_guild_init();
- client->guilds_length = 1; /* we don't dc_add_guild because id=0 */
- client->guilds[0]->name = strdup("Direct messages"); /* TODO: gettext for i18n */
- client->guilds[0]->client = client;
- }
- if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_START) {
- fprintf(stderr, "new DM start parsing object\n");
- /* dc_channel_free(pass->api_io.channel); */ /* parser branches must not leave */
- pass->api_io.channel = dc_channel_init(); /* behind any content in api_io */
- pass->api_io.channel->status |= DC_IN_PROGRESS;
- pass->api_io.channel->guild = client->guilds[0];
- }
- if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_END) {
- fprintf(stderr, "new DM (:\n");
- struct dc_channel ** channel = &client->guilds[0]->channel; /* 1. guild = DMs */
- while (*channel)
- channel = &(*channel)->next;
- pass->api_io.channel->status &= ~(DC_IN_PROGRESS);
- free(pass->api_io.channel->name);
+ if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER) && reason == LEJPCB_OBJECT_END) { /* if it was just a user */
+ pass->api_io.user->status &= ~DC_IN_PROGRESS;
+ pass->api_io.user = dc_addr_user(program, DC_ISAE(program->users), pass->api_io.user, DC_MAY_FREE);
+ if (path != DC_JSON_MESSAGE_AUTHOR && path != DC_JSON_MESSAGE_REFOBJ_AUTHOR && path != DC_JSON_MESSAGE_MENTION_USER && path != DC_JSON_MESSAGE_REFOBJ_MENTION_USER && !getenv("DC_0") /* override if those are disabled */) /* those expect a user parsed */
+ pass->api_io.user = NULL; /* when implementing parser: handle OBJECT_END */
+ else /* if something goes wrong - if those handlers do not null user, IO_MEMB_GC will */
+ pass->api_io.user->status |= DC_EXPLICIT_NULL; /* but will not free. */
+ } /* user parsing end */
+ if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_START) { /* client->guild[0] always */
+ fprintf(stderr, "new DM start parsing object\n"); /* exists */
+ /* dc_channel_free(pass->api_io.channel); */ /* parser branches must not leave */
+ pass->api_io.channel = dc_channel_init(); /* behind any content in api_io */
+ pass->api_io.channel->status |= DC_IN_PROGRESS;
+ pass->api_io.channel->guild = client->guilds[0];
+ }
+ if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_END) {
+ struct dc_channel ** channel = &client->guilds[0]->channel; /* 1. guild = DMs */
+ while (*channel)
+ channel = &(*channel)->next;
+ pass->api_io.channel->status &= ~(DC_IN_PROGRESS);
+ free(pass->api_io.channel->name);
pass->api_io.channel->name = strdup("");
for (size_t i = 0; i < pass->api_io.channel->users_length; i++) {
pass->api_io.channel->name = realloc(pass->api_io.channel->name, strlen(pass->api_io.channel->name)+strlen(pass->api_io.channel->users[i]->username)+1+2+1+4);
@@ -162,27 +134,19 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
strcat(pass->api_io.channel->name, pass->api_io.channel->users[i]->username);
strcat(pass->api_io.channel->name, buf);
}
- pass->api_io.channel = *channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE);
- if ((*channel = dc_find_ll_channel(client->guilds[0]->channel, pass->api_io.channel->id)))
- if (*channel != pass->api_io.channel) {
- dc_channel_free(pass->api_io.channel, DC_REPLACE);
- memmove(*channel, pass->api_io.channel, sizeof(**channel));
- }
- pass->api_io.channel->guild = client->guilds[0];
- pass->api_io.channel = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
- }
- if (reason & LEJP_FLAG_CB_IS_VALUE && pass->api_io.channel)
- switch (path) {
- case DC_JSON_DM_TYPE:
- pass->api_io.channel->type = atoi(ctx->buf);
- break;
- case DC_JSON_DM_ID:
- pass->api_io.channel->id = strtoull(ctx->buf, NULL, 10);
- break;
- default:
- break;
+ pass->api_io.channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE);
+ fprintf(stderr, "new DM id=%llu (:\n", pass->api_io.channel->id);
+ if ((*channel = dc_find_ll_channel(client->guilds[0]->channel, pass->api_io.channel->id))) {
+ fprintf(stderr, "DM already in LL, id=%llu\n", pass->api_io.channel->id);
+ if (*channel != pass->api_io.channel) {
+ dc_channel_free(*channel, DC_REPLACE);
+ memmove(*channel, pass->api_io.channel, sizeof(**channel));
}
+ }
+ pass->api_io.channel->guild = client->guilds[0];
+ pass->api_io.channel = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
}
+#if 0
if (startswith(ctx->path, dc_json_paths[DC_JSON_DM_USER])) { /* we don't DC_REPLACE here bcoz */
if (path == DC_JSON_DM_USER && reason == LEJPCB_OBJECT_START) { /* users never update. */
pass->api_io.user = dc_user_init();
@@ -213,14 +177,53 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char /* enum lejp_callbacks */ re
}
if (startswith(ctx->path, dc_json_paths[DC_JSON_GUILD])) {
if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_START) {
- pass->api_io.guild = dc_guild_init();
- pass->api_io.guild->status |= DC_IN_PROGRESS;
+ /* pass->api_io.guild = dc_guild_init();
+ pass->api_io.guild->status |= DC_IN_PROGRESS; */
}
if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_END) {
fprintf(stderr, "new guild");
- pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE);
+ /* pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE); */
}
}
+#endif
+ if (reason & LEJP_FLAG_CB_IS_VALUE)
+ switch (path) {
+ case DC_JSON_FRIEND: /* we assume we get users[] before relationships[] */
+ user = dc_find_user(program->users, program->users_length, strtoull(ctx->buf, NULL, 10));
+ if (user)
+ dc_add_user(DC_ISAE(client->users), user, DC_UNSET);
+ break;
+ case DC_JSON_DM_USER: /* we assume we get users[] before private_channels[] */
+ user = dc_find_user(program->users, program->users_length, strtoull(ctx->buf, NULL, 10));
+ if (user && pass->api_io.channel)
+ dc_add_user(DC_ISAE(pass->api_io.channel->users), user,DC_UNSET);
+ break;
+ case DC_JSON_ME_USERNAME: /* we are always checking for user because evil srv */
+ case DC_JSON_USER_NAME: /* might insert dots in keys and prevent OBJECT_CREATE */
+ if (pass->api_io.user && !pass->api_io.user->username) /* no trust srv */
+ pass->api_io.user->username = strdup(ctx->buf);
+ break;
+ case DC_JSON_ME_ID:
+ case DC_JSON_USER_ID:
+ if (pass->api_io.user)
+ pass->api_io.user->id = strtoll(ctx->buf, NULL, 10);
+ break;
+ case DC_JSON_ME_DISCRIMINATOR:
+ case DC_JSON_USER_DISCRIMINATOR:
+ if (pass->api_io.user)
+ pass->api_io.user->discriminator = atoi(ctx->buf);
+ break; /* yeah, we don't care about nicknames */
+ case DC_JSON_DM_TYPE:
+ if (pass->api_io.channel)
+ pass->api_io.channel->type = atoi(ctx->buf);
+ break;
+ case DC_JSON_DM_ID:
+ if (pass->api_io.channel)
+ pass->api_io.channel->id = strtoull(ctx->buf, NULL, 10);
+ break;
+ default:
+ break;
+ }
if (pass->packet == DC_NONE) /* useless to do anything BELOW if we haven't recvd packet type */
return '\0';
switch (pass->packet) { /* we fill in structs, set DC_INCOMPLETE and pass->parsing_status */
@@ -366,7 +369,7 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us,
pass->api_io.status &= ~DC_FROM_LWS;
break;
case LWS_CALLBACK_CLIENT_RECEIVE: /* websocket receive, pass to json parser ? */
- if (getenv("DC_N"))
+ if (getenv("DC_N")) /* output received network to stdout */
fprintf(stdout, "%.*s", len, (const unsigned char *) in);
if (pass->json_reason == LEJPCB_COMPLETE || pass->json_reason == LEJPCB_FAILED || !(pass->api_io.status & DC_LEJP_CONSTRUCTED)) { /* we regenerate a new context in case we didn't do that yet or in case the previous one finished parsing */
pass->api_io.status |= DC_LEJP_CONSTRUCTED;
@@ -389,8 +392,8 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us,
return -1;
}
dc_payload_free(pass->api_io.client->payloads[i], DC_UNSET);
- pass->api_io.client->payloads[i] = NULL;
- }
+ pass->api_io.client->payloads[i] = NULL; /* THIS MUST BE DONE, otherws */
+ } /* _free function will double free, because it frees till _sizeof */
pass->api_io.client->payloads_length = 0;
break;
default:
@@ -478,7 +481,7 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun
goto ws; /* we could call dc_api_i but that just fills stack */
break;
case DC_API_WS:
- if (getenv("DC_R"))
+ if (getenv("DC_R")) /* detect _WS calls */
raise(SIGINT);
fprintf(stderr, "DC_API_WS called\n");
ws: