File: methods.c

package info (click to toggle)
httpry 0.1.8-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 436 kB
  • sloc: ansic: 1,358; perl: 1,336; sh: 155; makefile: 62
file content (158 lines) | stat: -rw-r--r-- 4,171 bytes parent folder | download | duplicates (4)
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;
}