-
Notifications
You must be signed in to change notification settings - Fork 89
/
methods.c
159 lines (123 loc) · 4.14 KB
/
methods.c
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
----------------------------------------------------
httpry - HTTP logging and information retrieval tool
----------------------------------------------------
Copyright (c) 2005-2014 Jason Bittel <jason.bittel@gmail.com>
Licensed under GPLv2. For further information, see COPYING file.
*/
/*
The methods data structure is an unbalanced binary tree. All
packets are checked to see if they have a method contained
here; any packets that do not will be ignored.
This doesn't use a hash because the length of the potential
method is not known. At this point in the main processing
loop the packet data is still in a static buffer, so this
gives us a simpler solution. Perhaps at some point the flow
of the packet processing will be changed and we can switch
to a more traditional lookup table approach.
*/
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "error.h"
#include "methods.h"
#include "utility.h"
typedef struct method_node METHOD_NODE;
struct method_node {
char *method;
METHOD_NODE *left, *right;
};
static METHOD_NODE *methods = NULL;
int insert_method(char *str, size_t len);
void free_node(METHOD_NODE *node);
/* Parse and insert methods from methods string */
void parse_methods_string(char *str) {
char *method, *tmp, *i;
int num_methods = 0;
size_t len;
#ifdef DEBUG
ASSERT(str);
#endif
len = strlen(str);
if (len == 0)
LOG_DIE("Empty methods string provided");
/* Make a temporary copy of the string so we don't modify the original */
if ((tmp = str_duplicate(str)) == NULL)
LOG_DIE("Cannot allocate memory for methods string buffer");
for (i = tmp; (method = strtok(i, ",")); i = NULL) {
method = str_strip_whitespace(method);
method = str_tolower(method);
len = strlen(method);
if (len == 0) continue;
if (insert_method(method, len)) num_methods++;
}
free(tmp);
if (num_methods == 0)
LOG_DIE("No valid methods found in string");
return;
}
/* Insert a new method into the structure */
int insert_method(char *method, size_t len) {
METHOD_NODE **node = &methods;
int cmp;
#ifdef DEBUG
ASSERT(method);
ASSERT(strlen(method) > 0);
#endif
while (*node) {
cmp = str_compare(method, (*node)->method);
if (cmp > 0) {
node = &(*node)->right;
} else if (cmp < 0) {
node = &(*node)->left;
} else {
WARN("Method '%s' already provided", method);
return 0;
}
}
if ((*node = (METHOD_NODE *) malloc(sizeof(METHOD_NODE))) == NULL) {
LOG_DIE("Cannot allocate memory for method node");
}
if (((*node)->method = (char *) malloc(len + 1)) == NULL) {
LOG_DIE("Cannot allocate memory for method string");
}
str_copy((*node)->method, method, len + 1);
(*node)->left = (*node)->right = NULL;
return 1;
}
/* Search data structure for a matching method */
int is_request_method(const char *str) {
METHOD_NODE *node = methods;
int cmp;
#ifdef DEBUG
ASSERT(node);
ASSERT(str);
#endif
if (strlen(str) == 0) return 0;
while (node) {
cmp = str_compare(str, node->method);
if (cmp > 0) {
node = node->right;
} else if (cmp < 0) {
node = node->left;
} else {
return 1;
}
}
return 0;
}
/* Wrapper function to free allocated memory at program termination */
void free_methods() {
free_node(methods);
return;
}
/* Recursively free all children of the parameter node */
void free_node(METHOD_NODE *node) {
if (!node) return;
free_node(node->left);
free_node(node->right);
free(node->method);
free(node);
return;
}