1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
#include "query.h"
#include "benc.h"
#include "log.h"
#include <string.h>
#include <errno.h>
int handle_request(struct nodeid* self, const char* method, const char* packet, size_t packet_len, char** response, size_t response_len) {
if(strcmp(method, "ping") == 0) {
struct bcursor bcursor;
struct benc_node stream[256];
bcur_open(&bcursor, packet, packet+packet_len, stream, 256);
if(bcursor.readhead->type != BNT_DICT) {
err("Bad query: Packet is not a dict");
return QUERY_EBADQ;
}
if(bcur_next(&bcursor, 1) < 0) {
err("Bad query: No token after outer dict start");
return QUERY_EBADQ;
}
if(bcur_find_key(&bcursor, (const enum benc_nodetype[]){BNT_STRING}, (const char*[]){"a"}, (const size_t[]){1}, 1) != 0) {
err("Bad query: No arguments to request");
return QUERY_EBADQ;
}
bcur_next(&bcursor, 1);
if(bcursor.readhead->type != BNT_DICT) {
err("Bad query: Wrong value type for request");
return QUERY_EBADQ;
}
// Skip the dict element
bcur_next(&bcursor, 1);
bool source_set = false;
struct nodeid source_id;
while(bcursor.readhead->type != BNT_END) {
switch(bcur_find_key(&bcursor, (const enum benc_nodetype[]){BNT_STRING}, (const char*[]){"id"}, (const size_t[]){6}, 1)) {
case 0:
// Skip the key
bcur_next(&bcursor, 1);
if(bcursor.readhead->type != BNT_STRING) {
err("Bad query: Wrong value type for id");
return QUERY_EBADQ;
}
if(bcursor.readhead->size != 20) {
err("Bad query: Incorrect id length");
return QUERY_EBADQ;
}
source_set = true;
memcpy(&source_id, bcursor.readhead->loc, 20);
// Skip the value
bcur_next(&bcursor, 1);
break;
}
}
if(!source_set) {
err("Id argument not set");
return QUERY_EBADQ;
}
char* end = (*response) + response_len;
int rc = snprintf(*response, end-*response, "d2:id20:");
if(rc < 0)
return QUERY_EBADQ;
*response += rc;
memcpy(*response, self, sizeof(struct nodeid));
*response += sizeof(struct nodeid);
rc = snprintf(*response, end-*response, "ee");
if(rc < 0)
return QUERY_EBADQ;
*response += rc;
} else {
return QUERY_EUNK;
}
return 0;
}
|