summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bencoding.c65
-rw-r--r--src/dht.c14
-rw-r--r--utils/bencoding.c54
3 files changed, 116 insertions, 17 deletions
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 <bencoding.c>
#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;