summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-02-16 07:28:25 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2022-02-16 07:28:25 +0100
commitf6943ce36a18bf5ce91351af71de89d32ea772c7 (patch)
treefb6aa2b422d59a71fdf72738f8f8e2054ee3b320
parentgoing to use libcjson after all (diff)
downloaddiscord.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--.gitignore1
-rw-r--r--Makefile3
-rw-r--r--src/api.c45
-rw-r--r--src/h.c10
-rw-r--r--src/json.c18
-rw-r--r--src/main.c2
-rw-r--r--test/json.c6
7 files changed, 55 insertions, 30 deletions
diff --git a/.gitignore b/.gitignore
index 7ef384a..634b716 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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~
diff --git a/Makefile b/Makefile
index b5615f1..290da8e 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/src/api.c b/src/api.c
index 02878bf..7a48045 100644
--- a/src/api.c
+++ b/src/api.c
@@ -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 */
diff --git a/src/h.c b/src/h.c
index b08861e..83fafd8 100644
--- a/src/h.c
+++ b/src/h.c
@@ -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);
diff --git a/src/json.c b/src/json.c
index e23d934..4fcfcf5 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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);
diff --git a/src/main.c b/src/main.c
index d658caa..02b27da 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);