diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2022-02-16 07:28:25 +0100 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2022-02-16 07:28:25 +0100 |
commit | f6943ce36a18bf5ce91351af71de89d32ea772c7 (patch) | |
tree | fb6aa2b422d59a71fdf72738f8f8e2054ee3b320 | |
parent | going to use libcjson after all (diff) | |
download | discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar.gz discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar.bz2 discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar.lz discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar.xz discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.tar.zst discord.c-f6943ce36a18bf5ce91351af71de89d32ea772c7.zip |
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/api.c | 45 | ||||
-rw-r--r-- | src/h.c | 10 | ||||
-rw-r--r-- | src/json.c | 18 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | test/json.c | 6 |
7 files changed, 55 insertions, 30 deletions
@@ -4,6 +4,7 @@ a.out # debugging log files valgrind-out.txt .gdb_history +out.txt # files I like to keep in my WD src.old/ src/ui.glade~ @@ -1,5 +1,6 @@ DESTDIR=/ SRCFILE=src/main.c +BINFILE=discord.c O=0 CFLAGS += -Wextra -Wall -pedantic -g -O$O -Itmp -Isrc -I. -odiscord.c -Wno-unused-parameter -rdynamic -finput-charset=UTF-8 -fextended-identifiers LIBS += -lm @@ -47,7 +48,7 @@ valgrind-prepare: valgrind: -[ ! -f tmp/gend.supp ] && bash -c "echo '' > tmp/gend.supp" - G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind $(VGARGS) --suppressions=tmp/gend.supp ./discord.c + G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind $(VGARGS) --suppressions=tmp/gend.supp ./$(BINFILE) gensupp: cc misc/valgrind-supp-extractor.c -otmp/vse @@ -1,7 +1,9 @@ -#define DC_LOGIN_FORMAT "{\"login\":\"%s\",\"password\":\"%s\",\"undelete\":false,\"captcha_key\":null,\"login_source\":null,\"gift_code_sku_id\":null}" +#define DC_LOGIN_FORMAT "{\"login\":\"%s\",\"password\":\"%s\",\"undelete\":false," \ + "\"captcha_key\":null,\"login_source\":null,\"gift_code_sku_id\":null}" #define DC_COMPILE_INFO __VERSION__ " " __BASE_FILE__ " " __FILE__ " " __TIMESTAMP__ #define DC_STR(x) x -#define DC_USER_AGENT "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" /* this is so we can fool the login system */ +#define DC_USER_AGENT "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) " \ + "Chrome/90.0.4430.212 Safari/537.36" /* this is so we can fool the login system */ #define DC_SERVER_ADDRESS "discord.com" #define DC_SERVER_PORT 443 #define DC_SERVER_SSL 1 @@ -14,6 +16,14 @@ #define DC_API_PREFIX "/api/v9/" #define DC_LWS_ABLE_TO_PARSE_HEADERS 1 #define DC_RECONNECT_DELAY 10 +#define cJSON_GetObjectItem2(root, name1, name2) (cJSON_GetObjectItem(root, name1) ? /* mazohi= */ \ + cJSON_GetObjectItem(cJSON_GetObjectItem(root, name1), name2) : NULL) /* stično! */ +#define cJSON_GetObjectItem3(root, name1, name2, name3) (cJSON_GetObjectItem2(root, name1, name2) ? \ + cJSON_GetObjectItem(cJSON_GetObjectItem2(root, name1, name2), name3) : NULL) +#define cJSON_GetObjectItem4(ro, na1, na2, na3, na4) (cJSON_GetObjectItem3(ro, na1, na2, na3) ? \ + cJSON_GetObjectItem(cJSON_GetObjectItem3(ro, na1, na2, na3), na4) : NULL) +#define cJSON_GetObjectItem5(r, n1, n2, n3, n4, n5) (cJSON_GetObjectItem4(r, n1, n2, n3, n4) ? \ + cJSON_GetObjectItem(cJSON_GetObjectItem4(r, n1, n2, n3, n4), n5) : NULL) unsigned char dc_api_identify_u[] = { #include <identify.xxd> }; @@ -129,27 +139,26 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, case LWS_CALLBACK_CLOSED_CLIENT_HTTP: lwsl_user("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); break; - case LWS_CALLBACK_WSI_DESTROY: /* if I understand the docs correctly, this is allways */ + case LWS_CALLBACK_WSI_DESTROY: /* this is allways received */ if (pass->api_io.pass != pass) - fprintf(stderr, "[!!!] REPORT THIS BUG: pass->api_io.pass != pass\n"); + fprintf(stderr, "[!!!] REPORT BUG: pass->api_io.pass != pass\n"); if (pass->api_io.status & DC_DESTROY_CB) { pass->api_io.status |= DC_FROM_LWS; dc_api_i(pass->api_io); pass->api_io.status &= ~DC_FROM_LWS; } DC_API_IO_GC(pass->api_io); /* frees all unfinished parsing objects */ - pass->packet = DC_NONE; pass->api_io.client->pass = NULL; - dc_lws_pass_free(pass, DC_UNSET); /* called the last time us ptr & wsi r still */ - break; /* accessible - we can free the struct that was passed in as a heap ptr */ + dc_lws_pass_free(pass, DC_UNSET); /* called last time us ptr & wsi r still */ + break; case LWS_CALLBACK_WSI_CREATE: /* first - outermost - call with wsi present */ if (pass->api_io.client) { if (pass->api_io.status & DC_SET_PASS) { fprintf(stderr, "pass->api_io.client->pass = pass\n"); pass->api_io.client->pass = pass; } - if (pass->api_io.status & DC_SET_WS_ACTIVE) /* how to get if wsi is ws */ - pass->api_io.client->status |= DC_WS_ACTIVE; /* or http? IDFK. */ + if (pass->api_io.status & DC_SET_WS_ACTIVE) /* how to see if ws */ + pass->api_io.client->status |= DC_WS_ACTIVE; /* or http? */ } break; case LWS_CALLBACK_CLIENT_ESTABLISHED: /* websocket established */ @@ -163,17 +172,16 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: pass->reason = 0; if (len < 2) - fprintf(stderr, "SERVER CLOSED CONNECTION WITHOUT PROIVIDING REASON!\n"); + fprintf(stderr, "SERVER CLOSED CONNECTION W/O PROIVIDING REASON!\n"); else - pass->reason = ntohs(*(uint16_t *) in /* i sure hope this is legal */); + pass->reason = ntohs(*(uint16_t *) in /* i hope this is legal */); fprintf(stderr, "SERVER CLOSED CONNECTION WITH REASON %d\n", pass->reason); if (len > 2) - fprintf(stderr, "with additional message: %.*s\n", len-2, (char *) in+2); + fprintf(stderr, "with additional msg: %.*s\n", len-2, (char *) in+2); break; case LWS_CALLBACK_CLIENT_CLOSED: /* websocket closed */ pass->api_io.client->disconnect_time = time(NULL); DC_API_IO_GC(pass->api_io); /* frees all unfinished parsing objects */ - pass->packet = DC_NONE; pass->api_io.status = DC_NET_ERROR; pass->wsi = NULL; pass->api_io.status |= DC_FROM_LWS; @@ -183,8 +191,13 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, case LWS_CALLBACK_CLIENT_RECEIVE: /* websocket receive, pass to json parser ? */ if (getenv("DC_N")) /* output received network to stdout */ fprintf(stdout, "%.*s", len, (const unsigned char *) in); + char * serialized = dc_json(pass->json, in, len); + while (serialized) { + + serialized = dc_json(handler, NULL, 0); + } break; - case LWS_CALLBACK_CLIENT_WRITEABLE: /* invoke with lws_callback_on_writeable(wsi) 4 ws */ + case LWS_CALLBACK_CLIENT_WRITEABLE: /* invoke w/ lws_callback_on_writeable(wsi)4ws */ if (!pass->api_io.client) /* we empty all payloads from 0 to finish */ break; for (size_t i = 0; i < pass->api_io.client->payloads_length; i++) { @@ -234,7 +247,7 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun info.host = info.address; /* info.origin = DC_SERVER_ORIGIN; */ /* just don't send it */ info.method = "POST"; - pass = calloc(1, sizeof(struct dc_lws_pass)); /* cb frees */ + pass = dc_lws_pass_init(); /* cb frees */ fprintf(stderr, "allocated pass at %p\n", (void *) pass); i.status |= DC_DESTROY_CB; /* so that lws_cb will call api on destroy - fin rq */ pass->body_length = asprintf(&pass->body, DC_LOGIN_FORMAT, i.client->email, i.client->password); @@ -300,7 +313,7 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun #endif info.protocol = dc_lws_protocols[0].name; info.local_protocol_name = info.protocol; - pass = calloc(1, sizeof(struct dc_lws_pass)); + pass = dc_lws_pass_init(); i.type = DC_API_WS_CB; i.status |= DC_SET_PASS | DC_SET_WS_ACTIVE; i.status &= ~DC_DESTROY_CB; /* this is only for http requests */ @@ -373,11 +373,9 @@ struct dc_lws_pass { /* struct that is allocated for in dc_lws_cb unique per con char headers[DC_LWS_HEADERS_LENGTH][DC_LWS_MAX_HEADER_LENGTH]; /* nofree, a static 2d array */ int status; /* HTTP response code /\ headers contain request headers, then resp. */ struct dc_api_io api_io; /* so dc_api_io can decide what shall be passed into _CB */ - struct lejp_ctx json_ctx; /* holds a context for lejp */ - enum lejp_callbacks json_reason; /* holds last reason sent to json callback */ struct lws * wsi; /* set on ESTABLISHED and NULLed on CLOSED or ERROR */ - enum dc_ws_packet packet; /* what type of packet are we currently handling in lejp */ uint16_t reason; /* reason for closing connection */ + struct dc_json * json; /* dc_json for detecting start/end */ /* temporary debug things */ char * cp; int len; @@ -629,10 +627,16 @@ void dc_attached_function_free (struct dc_attached_function * s, enum dc_status if (!(t & DC_REPLACE)) free(s); } +struct dc_lws_pass * dc_lws_pass_init () { + struct dc_lws_pass * s = calloc(1, sizeof(*s)); + s->json = dc_json_init(); + return s; +} void dc_lws_pass_free (struct dc_lws_pass * s, enum dc_status t) { if (!s) return; free(s->body); + dc_json_free(s->json); /* only frees contents */ DC_API_IO_GC(s->api_io); if (!(t & DC_REPLACE)) free(s); @@ -10,9 +10,9 @@ struct dc_json { /* does not care about syntax, only purpose is to detect object char backup; /* internal we store byte we overwrote with \0 when we were ready */ int ready; /* internal we indicate to the next call that we were ready previous time */ }; /* note that no memory is transfered. in is copied and return mustn't be freed. */ -char * dc_json (struct dc_json * j, char * in) { /* detects start/end of a cat objects JSON stream */ - size_t i; /* input a null terminated string - a chunk of the json stream */ - if (!j->buf) +char * dc_json (struct dc_json * j, const char * in, int ln) { /* detects start/end in JSON stream */ + size_t i; /* input a null terminated string and ln==-1 - a chunk of the json stream */ + if (!j->buf) /* of if you know the length or string is not null terminated, set ln. */ (j->buf = malloc((j->bufcap = 1024) * sizeof(char)))[0] = '\0'; if (j->ready) { if (j->ready > 0) @@ -20,12 +20,13 @@ char * dc_json (struct dc_json * j, char * in) { /* detects start/end of a cat o j->buf[0] = j->backup; } size_t bufstrlen = strlen(j->buf); /* could optimize and cache it into the struct */ - size_t instrlen = strlen(in); + if (ln == -1) + ln = strlen(in); i = bufstrlen; - if (bufstrlen + instrlen > j->bufcap) - j->buf = realloc(j->buf, (j->bufcap=(bufstrlen+instrlen)*DC_REALLOC_K)*sizeof(char)); + if (bufstrlen + ln > j->bufcap) + j->buf = realloc(j->buf, (j->bufcap=(bufstrlen+ln)*DC_REALLOC_K)*sizeof(char)); strcpy(j->buf+bufstrlen, in); - bufstrlen += instrlen; + bufstrlen += ln; while (i < bufstrlen) { if (j->instr) { if (j->buf[i] == '"') { @@ -74,6 +75,9 @@ next: } return NULL; } /* returns pointer to null terminated string when there's an object to be parsed or NULL. */ +struct dc_json * dc_json_init () { + return calloc(1, sizeof(struct dc_json)); +} void dc_json_free (struct dc_json * s) { free(s->buf); free(s); @@ -4,6 +4,8 @@ #include <libwebsockets.h> #include <assert.h> #include <signal.h> +#include <cjson/cJSON.h> +#include <json.c> #include <lib.c> #include <ui.c> #include <api.c> diff --git a/test/json.c b/test/json.c index 6671628..33083dd 100644 --- a/test/json.c +++ b/test/json.c @@ -3,12 +3,12 @@ #include <string.h> #include <json.c> int main (int argc, char ** argv) { - struct dc_json * handler = calloc(1, sizeof(struct dc_json)); + struct dc_json * handler = dc_json_init(); char * o; for (int i = 1; i < argc; i++) - if ((o = dc_json(handler, argv[i]))) { + if ((o = dc_json(handler, argv[i], strlen(argv[i])))) { printf("%s\n", o); - while ((o = dc_json(handler, ""))) + while ((o = dc_json(handler, NULL, 0))) printf("%s\n", o); } dc_json_free(handler); |