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
|
/*
----------------------------------------------------
httpry - HTTP logging and information retrieval tool
----------------------------------------------------
Copyright (c) 2005-2014 Jason Bittel <jason.bittel@gmail.com>
*/
/*
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;
}
|