From a36d9a1b09a6632fd66ad67c7ba0c9692b058608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Mon, 21 Nov 2022 22:13:04 +0100 Subject: fixes --- src/bencoding.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++----- src/dht.c | 14 ++++++++++++ utils/bencoding.c | 54 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 src/dht.c diff --git a/src/bencoding.c b/src/bencoding.c index d1324c7..d1ac517 100644 --- a/src/bencoding.c +++ b/src/bencoding.c @@ -21,11 +21,12 @@ struct bencoding { struct bencoding * next; /**< NULL if element is not member of a list or dict */ struct bencoding * prev; struct bencoding * child; /**< NULL if element is not a list or dict or if it has 0 children */ + struct bencoding * parent; enum benc type; /**< type | opts of this element */ struct bencoding * key; /**< the key element, string according to the spec, applicable for dict */ char * value; /**< set to the content of the element, value is not null terminated unless terminate opt is set. NULL for dict and list. */ size_t valuelen; /**< length of string value, as value is not null terminated, internal value for list or dict. */ - int intvalue; + long int intvalue; int index; char oldterminator; /**< when opts&terminate, the character that was replaced with \0 is stored here */ char oldterminatorls; /**< when opts&terminate when there was no more space, replaced character is stored here. @@ -60,7 +61,7 @@ void free_bencoding (struct bencoding * b) { * @param a [in] the character in question */ -int b2json_charsize (char a) { +int b2json_charsize (unsigned char a) { if (a == '"') return 2; if (a == '\\') @@ -88,7 +89,7 @@ int b2json_charsize (char a) { * @return the destination pointer, incremented for the number of bytes written */ -char * b2json_charrepr (char * dest, char a) { +char * b2json_charrepr (char * dest, unsigned char a) { switch (a) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstringop-truncation" @@ -147,7 +148,7 @@ int b2json_length (struct bencoding * b) { } if (b->type & num) { char buf[512]; - sprintf(buf, "%d", b->intvalue); + sprintf(buf, "%ld", b->intvalue); return strlen(buf); } if (b->type & list) { @@ -204,7 +205,7 @@ char * b2json (char * dest, struct bencoding * b) { } if (b->type & num) { char buf[512]; - sprintf(buf, "%d", b->intvalue); + sprintf(buf, "%ld", b->intvalue); strncpy(dest, buf, strlen(buf)); return dest+strlen(buf); } @@ -318,6 +319,8 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) { if (oldarbeit && oldarbeit->type & string && oldarbeit->type & terminate && oldarbeit->oldterminator) c[0] = oldarbeit->oldterminator; arbeit = bdecode(c, len == -1 ? -1 : len-(c-s), opts); + if (arbeit) + arbeit->parent = b; if (oldarbeit && oldarbeit->type & string && oldarbeit->type & terminate && oldarbeit->oldterminator) c[0] = '\0'; if (!arbeit) /* bdecoding failed or last element */ @@ -362,6 +365,7 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) { return NULL; default: if (!(s[0] >= '0' && s[0] <= '9')) { /* not a string. not checking this would allow DoS for parsing "lx" */ + fprintf(stderr, "bencoding: unknown type %c\n", s[0]); free(b); return NULL; } @@ -389,6 +393,55 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) { /** * returns a pointer to bencoding struct matching bencoding path or NULL if not found + * + * path key/key2/key3 will given object {"key":{"key2":{"key3":val}}} return val * - * [xxx] specifies xxxth child of a dict or list. if + * @param benc [in] the bencoding dict to look in + * @param key [in] the path */ + +struct bencoding * bpath (struct bencoding * benc, const char * key) { + if (!benc) + return NULL; + if (!benc->child) + return NULL; + benc = benc->child; + if (key[0] == '/') + key++; + size_t len = strlen(key); + char * c = strchr(key, '/'); + if (c) + len = c - key; + while (benc) { + if (benc->key && benc->key->type & num) { + char buf[512]; + sprintf(buf, "%ld", strtol(key, NULL, 10)); + if (!strncmp(buf, key, len) && benc->key->intvalue == strtol(key, NULL, 10)) { + if (!c) + return benc; + else + return bpath(benc, key+len); + } + } + if (benc->key && benc->key->type & string) { + if (!strncmp(key, benc->key->value, MIN(benc->key->valuelen, len))) { + if (!c) + return benc; + else + return bpath(benc, key+len); + } + } + benc = benc->next; + } + return NULL; +} + +/** + * macro that loops following code body across a list or values of dict + * + * @param elem [out] name of element that will be used for value while looping + * @param list [in] list/dict of values + */ + +#define bforeach(elem, list) \ + for (struct bencoding * elem = list ? list->child : NULL; elem; elem = elem->next) diff --git a/src/dht.c b/src/dht.c new file mode 100644 index 0000000..629bf26 --- /dev/null +++ b/src/dht.c @@ -0,0 +1,14 @@ +struct dht { + char id[20]; + int socket; +}; +struct node { + char id[20]; + int lost; + int sent; + int answers; + int malformed; + int received; + time_t last; + struct sockaddr addr; +}; diff --git a/utils/bencoding.c b/utils/bencoding.c index a60e1b3..ae80546 100644 --- a/utils/bencoding.c +++ b/utils/bencoding.c @@ -7,29 +7,61 @@ #include #define S0(x) (x ? x : "") int main (int argc, char ** argv) { - if (argc != 1+1) - error_at_line(1, 0, __FILE__, __LINE__, "%s encode < json || %s decode < bencoding", S0(argv[0]), S0(argv[0])); + if (argc < 1+1) + error_at_line(1, 0, __FILE__, __LINE__, "%s encode < json || %s decode < bencoding || %s path path/to/obj < bencoding || %s foreach < bencoding", S0(argv[0]), S0(argv[0]), S0(argv[0]), S0(argv[0])); + if (argv[1][0] == 'p' && argc != 1+2) + error_at_line(1, 0, __FILE__, __LINE__, "set path!"); int size = 2048; int len = 0; char * in = malloc(size); while (!feof(stdin) && !ferror(stdin)) { if (!in) error_at_line(2, 0, __FILE__, __LINE__, "heap alloc failed"); - len += fread(in, 1, size-len-1, stdin); + len += fread(in+len, 1, size-len-1, stdin); if ((size - len) < 1024) in = realloc(in, size *= 2); } if (argv[1][0] == 'e') error_at_line(3, 0, __FILE__, __LINE__, "N/I"); struct bencoding * bencoding = bdecode(in, size, terminate); - len = b2json_length(bencoding); - char out[len+1]; - char * end = b2json(out, bencoding); - *end = '\0'; - puts(out); - if (end - out != len) - error_at_line(4, 0, __FILE__, __LINE__, "b2json wrote %ld instead of %d bytes.", end-out, len); - fprintf(stderr, "len: %d\n", len); + if (argv[1][0] == 'd') { + len = b2json_length(bencoding); + char out[len+1]; + char * end = b2json(out, bencoding); + *end = '\0'; + puts(out); + if (end - out != len) + error_at_line(4, 0, __FILE__, __LINE__, "b2json wrote %ld instead of %d bytes.", end-out, len); + fprintf(stderr, "len: %d\n", len); + } + if (argv[1][0] == 'p') { + len = b2json_length(bpath(bencoding, argv[2])); + char out[len+1]; + char * end = b2json(out, bpath(bencoding, argv[2])); + *end = '\0'; + puts(out); + if (end - out != len) + error_at_line(4, 0, __FILE__, __LINE__, "b2json wrote %ld instead of %d bytes.", end-out, len); + fprintf(stderr, "len: %d\n", len); + } + if (argv[1][0] == 'f') { + bforeach (value, bencoding) { + len = b2json_length(value->key); + char out[len+1]; + char * end = b2json(out, value->key); + *end = '\0'; + if (end - out != len) + error_at_line(4, 0, __FILE__, __LINE__, "b2json wrote %ld instead of %d bytes.", end-out, len); + printf("key(%d): %s\n", len, out); + len = b2json_length(value); + char out2[len+1]; + end = b2json(out2, value); + *end = '\0'; + if (end - out2 != len) + error_at_line(4, 0, __FILE__, __LINE__, "b2json wrote %ld instead of %d bytes.", end-out2, len); + printf("value(%d): %s\n", len, out2); + } + } free_bencoding(bencoding); free(in); return 0; -- cgit v1.2.3