├── .gitignore ├── Makefile ├── README.md ├── common ├── queue.h ├── rb_test.c ├── rbtree.c ├── rbtree.h ├── rdtsc.h ├── test ├── time.c └── time.h ├── lib └── json │ ├── AUTHORS │ ├── COPYING │ ├── ChangeLog │ ├── INSTALL │ ├── Makefile.am │ ├── Makefile.in │ ├── NEWS │ ├── README │ ├── README-WIN32.html │ ├── README.html │ ├── aclocal.m4 │ ├── arraylist.c │ ├── arraylist.h │ ├── bits.h │ ├── config.guess │ ├── config.h │ ├── config.h.in │ ├── config.h.win32 │ ├── config.sub │ ├── configure │ ├── configure.in │ ├── debug.c │ ├── debug.h │ ├── depcomp │ ├── install-sh │ ├── json.h │ ├── json.pc │ ├── json.pc.in │ ├── json_object.c │ ├── json_object.h │ ├── json_object_private.h │ ├── json_tokener.c │ ├── json_tokener.h │ ├── json_util.c │ ├── json_util.h │ ├── linkhash.c │ ├── linkhash.h │ ├── ltmain.sh │ ├── missing │ ├── printbuf.c │ ├── printbuf.h │ ├── stamp-h1 │ ├── test1.c │ ├── test2.c │ └── test3.c └── src ├── args_parser.c ├── args_parser.h ├── hash.c ├── hash.h ├── hash_test.c ├── http.h ├── http_bd.c ├── http_bd.h ├── http_conn.c ├── http_impl.c ├── http_impl.h ├── http_parser.c ├── http_str.c ├── http_str.h ├── log.c ├── log.h ├── main.c ├── memqueue.c ├── memqueue.h ├── memqueue_expiry.c ├── memqueue_impl.h ├── rbtree.c ├── rbtree.h ├── router.c ├── router.h ├── sock_easy.c ├── sock_easy.h ├── time.c └── time.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.so 3 | *.o 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | src = src/log.c src/http_impl.c src/http_parser.c src/http_str.c \ 2 | src/router.c src/rbtree.c src/hash.c src/sock_easy.c src/http_conn.c \ 3 | src/memqueue_expiry.c src/memqueue.c src/time.c src/http_bd.c src/main.c \ 4 | src/args_parser.c 5 | gccflags = -g 6 | 7 | memqueue : $(src) 8 | gcc -L/usr/local/lib -I/usr/local/include $(gccflags) -Wall -lm -ljson -llthread -lpcre $(src) -Werror -llthread -lpthread -o memqueue 9 | 10 | install: memqueue 11 | cp memqueue /usr/local/bin/memqueue 12 | 13 | clean: 14 | rm -f memqueue *.o *.so 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | memqueue 2 | ======== 3 | 4 | Introduction 5 | ------------ 6 | 7 | memqueue is an in-memory queue server. Its goal is to share messages across multiple consumers polling from the same queue where each consumer can consume at their own pace without missing messages. This is made possible by using message expiry and queue revisions. 8 | 9 | memqueue queues get a new revision each time a message is inserted. Consumers can specify which revision they want to poll from, allowing them to consume 10 | messages that have already been consumed but are not expired yet. 11 | 12 | ## Example 13 | 14 | A good example that illustrates memqueue's features is a group chat server over HTTP. 15 | We'll create a single queue for the group. Each user will poll from this queue waiting for new messages and when a new message arrives, the queue revision is bumped by one and the message get sent to all consumers along with the latest revision. During the time a consumer is consuming a message and reconnecting, new messages can come in and the queue revision can be bumped by few digits. This is not an issue because the next time each of the consumers connect, they'll provide the revision they are at and the poll will retrieve all the messages they have missed after this revision. 16 | 17 | # memqueue REST API 18 | 19 | memqueue has an HTTP REST interface and runs its own HTTP server built on top of [lthread](https://github.com/halayli/lthread/). Websocket support is on the TODO list. 20 | 21 | ###Create a new queue in memory 22 | 23 | PUT / 24 | 25 | **parameters** 26 | 27 | `expiry: Integer (ms)`. (Optional) 28 | 29 | Milliseconds of queue inactivity before it get's removed. Queue activity can be either queue polling or posting a new message. 30 | 31 | `max_size: Integer`. (Optional) 32 | 33 | Number of messages a queue will hold before it either starts dropping messages from head or rejects messages depending on the parameter *drop_from_head*. 34 | 35 | `drop_from_head: Boolean (0 or 1)`. (Optional) 36 | 37 | if *max_size* is specified, and the queue is full, this parameter specifies whether to drop a message from head and insert a new one at tail or reject the message. 38 | 39 | `consumer_expiry: Integer (ms)`. (optional) 40 | 41 | If set, consumers can specify their `` when polling to inform other consumers that `` started polling. memqueue only inform other consumers about *new* consumers. A consumer is considered new if he hasn't been seen polling in the last *consumer_expiry* period. 42 | 43 | ###Post a message to `` 44 | 45 | POST / 46 | 47 | **Parameters** 48 | 49 | `expiry: Integer (ms)`. (optional) 50 | 51 | Message `data` must be included in the HTTP POST body 52 | 53 | ###Poll messages from `` 54 | 55 | GET / 56 | 57 | **Parameters** 58 | 59 | `rev: Integer`. (optional) 60 | 61 | `timeout: Integer (ms)`. (optional) 62 | 63 | `latest: Boolean(0 or 1)`. (optional) 64 | 65 | `consumer_id: String`. (optional) 66 | 67 | `include_consumers: Boolean(0 or 1)`. (Optional) 68 | 69 | ###Poll from multiple queues 70 | 71 | GET /mpoll 72 | 73 | **Parameters** 74 | 75 | Takes the same parameters as GET / `` with a -`` appended to the parameter where `` is an integer grouping each of the queue parameters. 76 | 77 | `total_queues: Integer`. (required) 78 | 79 | Specifies the total number of queues you are polling from. 80 | 81 | ###Delete queue `` 82 | 83 | DELETE / 84 | -------------------------------------------------------------------------------- /common/rb_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "time.h" 4 | #include "rbtree.h" 5 | 6 | struct _obj_t { 7 | int key; 8 | struct rb_node node; 9 | char data[32]; 10 | }; 11 | 12 | typedef struct _obj_t obj_t; 13 | 14 | obj_t* 15 | my_search(struct rb_root *root, int key) 16 | { 17 | struct rb_node *node = root->rb_node; 18 | 19 | while (node) { 20 | obj_t *data = container_of(node, struct _obj_t, node); 21 | int result; 22 | 23 | result = key - data->key; 24 | 25 | if (result < 0) 26 | node = node->rb_left; 27 | else if (result > 0) 28 | node = node->rb_right; 29 | else 30 | return data; 31 | } 32 | 33 | return NULL; 34 | } 35 | 36 | int 37 | rb_insert_obj(struct rb_root *root, obj_t *data) 38 | { 39 | obj_t *this; 40 | struct rb_node **p = &(root->rb_node), *parent = NULL; 41 | 42 | while (*p) 43 | { 44 | parent = *p; 45 | this = container_of(*p, struct _obj_t, node); 46 | int result = data->key - this->key; 47 | 48 | parent = *p; 49 | if (result < 0) 50 | p = &(*p)->rb_left; 51 | else if (result > 0) 52 | p = &(*p)->rb_right; 53 | else 54 | return -1; 55 | } 56 | 57 | rb_link_node(&data->node, parent, p); 58 | rb_insert_color(&data->node, root); 59 | 60 | return 0; 61 | } 62 | #define MAX_SET 100000 63 | #define SEARCH_SET 5 64 | _time_t duration[MAX_SET]; 65 | int search_set[SEARCH_SET] = {432, 51236, 234124, 432342323, 4232}; 66 | int main (void) 67 | { 68 | struct rb_root mytree = RB_ROOT; 69 | obj_t *obj = NULL; 70 | int i, ret; 71 | _time_t t1, t2,t3; 72 | 73 | for (i = 0; i< MAX_SET; i++) { 74 | obj_t *o1 = malloc(sizeof(obj_t)); 75 | o1->key = i; 76 | t1 = rdtsc(); 77 | ret = rb_insert_obj(&mytree, o1); 78 | t2 = rdtsc(); 79 | duration[i] = tick_diff_usecs(t1, t2); 80 | if (ret != 0) 81 | printf("failed to insert %d in tree\n", i); 82 | } 83 | 84 | for (i = 0; i < SEARCH_SET; i++) { 85 | t1 = rdtsc(); 86 | obj = my_search(&mytree, search_set[i]); 87 | t2 = rdtsc(); 88 | t3 = tick_diff_usecs(t1, t2); 89 | 90 | if (obj) { 91 | printf("found obj %d in %llu usecs\n", obj->key, t3); 92 | } else 93 | printf("obj not found in %llu usecs\n", t3); 94 | } 95 | printf("sleeping for 10 secs\n"); 96 | sleep(10); 97 | 98 | for (i = 0; i< MAX_SET; i++) { 99 | if (duration[i] > 0) 100 | printf("obj %d took %llu to insert\n", i, duration[i]); 101 | } 102 | for (i = 0; i< MAX_SET; i++) { 103 | if (duration[i] > 5) 104 | printf("obj %d took %llu to insert\n", i, duration[i]); 105 | } 106 | 107 | printf("sleeping for 10 secs\n"); 108 | sleep(10); 109 | for (i = 0; i< MAX_SET; i++) { 110 | t1 = rdtsc(); 111 | obj = my_search(&mytree, i); 112 | if (obj) { 113 | rb_erase(&obj->node, &mytree); 114 | free(obj); 115 | } 116 | t2 = rdtsc(); 117 | t3 = tick_diff_usecs(t1, t2); 118 | duration[i] = tick_diff_usecs(t1, t2); 119 | } 120 | for (i = 0; i< MAX_SET; i++) { 121 | if (duration[i] > 5) 122 | printf("obj %d took %llu to find/delete\n", i, duration[i]); 123 | } 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /common/rbtree.c: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | (C) 2002 David Woodhouse 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | linux/lib/rbtree.c 21 | */ 22 | 23 | #include "rbtree.h" 24 | 25 | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 26 | { 27 | struct rb_node *right = node->rb_right; 28 | struct rb_node *parent = rb_parent(node); 29 | 30 | if ((node->rb_right = right->rb_left)) 31 | rb_set_parent(right->rb_left, node); 32 | right->rb_left = node; 33 | 34 | rb_set_parent(right, parent); 35 | 36 | if (parent) 37 | { 38 | if (node == parent->rb_left) 39 | parent->rb_left = right; 40 | else 41 | parent->rb_right = right; 42 | } 43 | else 44 | root->rb_node = right; 45 | rb_set_parent(node, right); 46 | } 47 | 48 | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 49 | { 50 | struct rb_node *left = node->rb_left; 51 | struct rb_node *parent = rb_parent(node); 52 | 53 | if ((node->rb_left = left->rb_right)) 54 | rb_set_parent(left->rb_right, node); 55 | left->rb_right = node; 56 | 57 | rb_set_parent(left, parent); 58 | 59 | if (parent) 60 | { 61 | if (node == parent->rb_right) 62 | parent->rb_right = left; 63 | else 64 | parent->rb_left = left; 65 | } 66 | else 67 | root->rb_node = left; 68 | rb_set_parent(node, left); 69 | } 70 | 71 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 72 | { 73 | struct rb_node *parent, *gparent; 74 | 75 | while ((parent = rb_parent(node)) && rb_is_red(parent)) 76 | { 77 | gparent = rb_parent(parent); 78 | 79 | if (parent == gparent->rb_left) 80 | { 81 | { 82 | register struct rb_node *uncle = gparent->rb_right; 83 | if (uncle && rb_is_red(uncle)) 84 | { 85 | rb_set_black(uncle); 86 | rb_set_black(parent); 87 | rb_set_red(gparent); 88 | node = gparent; 89 | continue; 90 | } 91 | } 92 | 93 | if (parent->rb_right == node) 94 | { 95 | register struct rb_node *tmp; 96 | __rb_rotate_left(parent, root); 97 | tmp = parent; 98 | parent = node; 99 | node = tmp; 100 | } 101 | 102 | rb_set_black(parent); 103 | rb_set_red(gparent); 104 | __rb_rotate_right(gparent, root); 105 | } else { 106 | { 107 | register struct rb_node *uncle = gparent->rb_left; 108 | if (uncle && rb_is_red(uncle)) 109 | { 110 | rb_set_black(uncle); 111 | rb_set_black(parent); 112 | rb_set_red(gparent); 113 | node = gparent; 114 | continue; 115 | } 116 | } 117 | 118 | if (parent->rb_left == node) 119 | { 120 | register struct rb_node *tmp; 121 | __rb_rotate_right(parent, root); 122 | tmp = parent; 123 | parent = node; 124 | node = tmp; 125 | } 126 | 127 | rb_set_black(parent); 128 | rb_set_red(gparent); 129 | __rb_rotate_left(gparent, root); 130 | } 131 | } 132 | 133 | rb_set_black(root->rb_node); 134 | } 135 | 136 | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 137 | struct rb_root *root) 138 | { 139 | struct rb_node *other; 140 | 141 | while ((!node || rb_is_black(node)) && node != root->rb_node) 142 | { 143 | if (parent->rb_left == node) 144 | { 145 | other = parent->rb_right; 146 | if (rb_is_red(other)) 147 | { 148 | rb_set_black(other); 149 | rb_set_red(parent); 150 | __rb_rotate_left(parent, root); 151 | other = parent->rb_right; 152 | } 153 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 154 | (!other->rb_right || rb_is_black(other->rb_right))) 155 | { 156 | rb_set_red(other); 157 | node = parent; 158 | parent = rb_parent(node); 159 | } 160 | else 161 | { 162 | if (!other->rb_right || rb_is_black(other->rb_right)) 163 | { 164 | rb_set_black(other->rb_left); 165 | rb_set_red(other); 166 | __rb_rotate_right(other, root); 167 | other = parent->rb_right; 168 | } 169 | rb_set_color(other, rb_color(parent)); 170 | rb_set_black(parent); 171 | rb_set_black(other->rb_right); 172 | __rb_rotate_left(parent, root); 173 | node = root->rb_node; 174 | break; 175 | } 176 | } 177 | else 178 | { 179 | other = parent->rb_left; 180 | if (rb_is_red(other)) 181 | { 182 | rb_set_black(other); 183 | rb_set_red(parent); 184 | __rb_rotate_right(parent, root); 185 | other = parent->rb_left; 186 | } 187 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 188 | (!other->rb_right || rb_is_black(other->rb_right))) 189 | { 190 | rb_set_red(other); 191 | node = parent; 192 | parent = rb_parent(node); 193 | } 194 | else 195 | { 196 | if (!other->rb_left || rb_is_black(other->rb_left)) 197 | { 198 | rb_set_black(other->rb_right); 199 | rb_set_red(other); 200 | __rb_rotate_left(other, root); 201 | other = parent->rb_left; 202 | } 203 | rb_set_color(other, rb_color(parent)); 204 | rb_set_black(parent); 205 | rb_set_black(other->rb_left); 206 | __rb_rotate_right(parent, root); 207 | node = root->rb_node; 208 | break; 209 | } 210 | } 211 | } 212 | if (node) 213 | rb_set_black(node); 214 | } 215 | 216 | void rb_erase(struct rb_node *node, struct rb_root *root) 217 | { 218 | struct rb_node *child, *parent; 219 | int color; 220 | 221 | if (!node->rb_left) 222 | child = node->rb_right; 223 | else if (!node->rb_right) 224 | child = node->rb_left; 225 | else 226 | { 227 | struct rb_node *old = node, *left; 228 | 229 | node = node->rb_right; 230 | while ((left = node->rb_left) != NULL) 231 | node = left; 232 | 233 | if (rb_parent(old)) { 234 | if (rb_parent(old)->rb_left == old) 235 | rb_parent(old)->rb_left = node; 236 | else 237 | rb_parent(old)->rb_right = node; 238 | } else 239 | root->rb_node = node; 240 | 241 | child = node->rb_right; 242 | parent = rb_parent(node); 243 | color = rb_color(node); 244 | 245 | if (parent == old) { 246 | parent = node; 247 | } else { 248 | if (child) 249 | rb_set_parent(child, parent); 250 | parent->rb_left = child; 251 | 252 | node->rb_right = old->rb_right; 253 | rb_set_parent(old->rb_right, node); 254 | } 255 | 256 | node->rb_parent_color = old->rb_parent_color; 257 | node->rb_left = old->rb_left; 258 | rb_set_parent(old->rb_left, node); 259 | 260 | goto color; 261 | } 262 | 263 | parent = rb_parent(node); 264 | color = rb_color(node); 265 | 266 | if (child) 267 | rb_set_parent(child, parent); 268 | if (parent) 269 | { 270 | if (parent->rb_left == node) 271 | parent->rb_left = child; 272 | else 273 | parent->rb_right = child; 274 | } 275 | else 276 | root->rb_node = child; 277 | 278 | color: 279 | if (color == RB_BLACK) 280 | __rb_erase_color(child, parent, root); 281 | } 282 | 283 | struct rb_node *rb_last(const struct rb_root *root) 284 | { 285 | struct rb_node *n; 286 | 287 | n = root->rb_node; 288 | if (!n) 289 | return NULL; 290 | while (n->rb_right) 291 | n = n->rb_right; 292 | return n; 293 | } 294 | 295 | struct rb_node *rb_next(const struct rb_node *node) 296 | { 297 | struct rb_node *parent; 298 | 299 | if (rb_parent(node) == node) 300 | return NULL; 301 | 302 | /* If we have a right-hand child, go down and then left as far 303 | as we can. */ 304 | if (node->rb_right) { 305 | node = node->rb_right; 306 | while (node->rb_left) 307 | node=node->rb_left; 308 | return (struct rb_node *)node; 309 | } 310 | 311 | /* No right-hand children. Everything down and left is 312 | smaller than us, so any 'next' node must be in the general 313 | direction of our parent. Go up the tree; any time the 314 | ancestor is a right-hand child of its parent, keep going 315 | up. First time it's a left-hand child of its parent, said 316 | parent is our 'next' node. */ 317 | while ((parent = rb_parent(node)) && node == parent->rb_right) 318 | node = parent; 319 | 320 | return parent; 321 | } 322 | 323 | struct rb_node *rb_prev(const struct rb_node *node) 324 | { 325 | struct rb_node *parent; 326 | 327 | if (rb_parent(node) == node) 328 | return NULL; 329 | 330 | /* If we have a left-hand child, go down and then right as far 331 | as we can. */ 332 | if (node->rb_left) { 333 | node = node->rb_left; 334 | while (node->rb_right) 335 | node=node->rb_right; 336 | return (struct rb_node *)node; 337 | } 338 | 339 | /* No left-hand children. Go up till we find an ancestor which 340 | is a right-hand child of its parent */ 341 | while ((parent = rb_parent(node)) && node == parent->rb_left) 342 | node = parent; 343 | 344 | return parent; 345 | } 346 | 347 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 348 | struct rb_root *root) 349 | { 350 | struct rb_node *parent = rb_parent(victim); 351 | 352 | /* Set the surrounding nodes to point to the replacement */ 353 | if (parent) { 354 | if (victim == parent->rb_left) 355 | parent->rb_left = new; 356 | else 357 | parent->rb_right = new; 358 | } else { 359 | root->rb_node = new; 360 | } 361 | if (victim->rb_left) 362 | rb_set_parent(victim->rb_left, new); 363 | if (victim->rb_right) 364 | rb_set_parent(victim->rb_right, new); 365 | 366 | /* Copy the pointers/colour from the victim to the replacement */ 367 | *new = *victim; 368 | } 369 | -------------------------------------------------------------------------------- /common/rbtree.h: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | linux/include/linux/rbtree.h 20 | 21 | To use rbtrees you'll have to implement your own insert and search cores. 22 | This will avoid us to use callbacks and to drop drammatically performances. 23 | I know it's not the cleaner way, but in C (not in C++) to get 24 | performances and genericity... 25 | 26 | Some example of insert and search follows here. The search is a plain 27 | normal search over an ordered tree. The insert instead must be implemented 28 | in two steps: First, the code must insert the element in order as a red leaf 29 | in the tree, and then the support library function rb_insert_color() must 30 | be called. Such function will do the not trivial work to rebalance the 31 | rbtree, if necessary. 32 | 33 | ----------------------------------------------------------------------- 34 | static inline struct page * rb_search_page_cache(struct inode * inode, 35 | unsigned long offset) 36 | { 37 | struct rb_node * n = inode->i_rb_page_cache.rb_node; 38 | struct page * page; 39 | 40 | while (n) 41 | { 42 | page = rb_entry(n, struct page, rb_page_cache); 43 | 44 | if (offset < page->offset) 45 | n = n->rb_left; 46 | else if (offset > page->offset) 47 | n = n->rb_right; 48 | else 49 | return page; 50 | } 51 | return NULL; 52 | } 53 | 54 | static inline struct page * __rb_insert_page_cache(struct inode * inode, 55 | unsigned long offset, 56 | struct rb_node * node) 57 | { 58 | struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 59 | struct rb_node * parent = NULL; 60 | struct page * page; 61 | 62 | while (*p) 63 | { 64 | parent = *p; 65 | page = rb_entry(parent, struct page, rb_page_cache); 66 | 67 | if (offset < page->offset) 68 | p = &(*p)->rb_left; 69 | else if (offset > page->offset) 70 | p = &(*p)->rb_right; 71 | else 72 | return page; 73 | } 74 | 75 | rb_link_node(node, parent, p); 76 | 77 | return NULL; 78 | } 79 | 80 | static inline struct page * rb_insert_page_cache(struct inode * inode, 81 | unsigned long offset, 82 | struct rb_node * node) 83 | { 84 | struct page * ret; 85 | if ((ret = __rb_insert_page_cache(inode, offset, node))) 86 | goto out; 87 | rb_insert_color(node, &inode->i_rb_page_cache); 88 | out: 89 | return ret; 90 | } 91 | ----------------------------------------------------------------------- 92 | */ 93 | 94 | #ifndef _RBTREE_H 95 | #define _RBTREE_H 96 | #include 97 | 98 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 99 | 100 | #define container_of(ptr, type, member) ({ \ 101 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 102 | (type *)( (char *)__mptr - offsetof(type,member) );}) 103 | 104 | 105 | struct rb_node 106 | { 107 | unsigned long rb_parent_color; 108 | #define RB_RED 0 109 | #define RB_BLACK 1 110 | struct rb_node *rb_right; 111 | struct rb_node *rb_left; 112 | } __attribute__((aligned(sizeof(long)))); 113 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 114 | 115 | struct rb_root 116 | { 117 | struct rb_node *rb_node; 118 | }; 119 | 120 | 121 | #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 122 | #define rb_color(r) ((r)->rb_parent_color & 1) 123 | #define rb_is_red(r) (!rb_color(r)) 124 | #define rb_is_black(r) rb_color(r) 125 | #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 126 | #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 127 | 128 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 129 | { 130 | rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 131 | } 132 | static inline void rb_set_color(struct rb_node *rb, int color) 133 | { 134 | rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 135 | } 136 | 137 | #define RB_ROOT (struct rb_root) { NULL, } 138 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 139 | 140 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 141 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 142 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 143 | 144 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 145 | extern void rb_erase(struct rb_node *, struct rb_root *); 146 | 147 | typedef void (*rb_augment_f)(struct rb_node *node, void *data); 148 | 149 | extern void rb_augment_insert(struct rb_node *node, 150 | rb_augment_f func, void *data); 151 | extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 152 | extern void rb_augment_erase_end(struct rb_node *node, 153 | rb_augment_f func, void *data); 154 | 155 | /* Find logical next and previous nodes in a tree */ 156 | extern struct rb_node *rb_next(const struct rb_node *); 157 | extern struct rb_node *rb_prev(const struct rb_node *); 158 | extern struct rb_node *rb_first(const struct rb_root *); 159 | extern struct rb_node *rb_last(const struct rb_root *); 160 | 161 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 162 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 163 | struct rb_root *root); 164 | 165 | static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 166 | struct rb_node ** rb_link) 167 | { 168 | node->rb_parent_color = (unsigned long )parent; 169 | node->rb_left = node->rb_right = NULL; 170 | 171 | *rb_link = node; 172 | } 173 | 174 | #endif /* _LINUX_RBTREE_H */ 175 | -------------------------------------------------------------------------------- /common/rdtsc.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDTSC_H_ 2 | #define _RDTSC_H_ 3 | 4 | #endif /* _RDTSC_H_ */ 5 | -------------------------------------------------------------------------------- /common/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/halayli/memqueue/1c04bc4b20d128ab7c0d0fc3d542a5f84bcb1ebf/common/test -------------------------------------------------------------------------------- /common/time.c: -------------------------------------------------------------------------------- 1 | #include "time.h" 2 | 3 | uint64_t 4 | tick_diff_usecs(uint64_t t1, uint64_t t2) 5 | { 6 | uint64_t t3 = 0; 7 | t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 8 | return t3; 9 | } 10 | 11 | uint64_t 12 | tick_diff_msecs(uint64_t t1, uint64_t t2) 13 | { 14 | uint64_t t3 = 0; 15 | t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 16 | return t3/1000; 17 | } 18 | 19 | uint64_t 20 | tick_diff_secs(uint64_t t1, uint64_t t2) 21 | { 22 | uint64_t t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 23 | return t3/1000000; 24 | } 25 | 26 | uint64_t 27 | rdtsc(void) 28 | { 29 | uint32_t a = 0, d = 0; 30 | 31 | asm volatile ("rdtsc" : "=a"(a), "=d"(d)); 32 | return (((uint64_t) d << 32) | a); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /common/time.h: -------------------------------------------------------------------------------- 1 | #ifndef _LT_TIME_ 2 | #define _LT_TIME_ 3 | #include 4 | 5 | uint64_t tick_diff_usecs(uint64_t t1, uint64_t t2); 6 | uint64_t tick_diff_msecs(uint64_t t1, uint64_t t2); 7 | uint64_t tick_diff_secs(uint64_t t1, uint64_t t2); 8 | uint64_t rdtsc(void); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /lib/json/AUTHORS: -------------------------------------------------------------------------------- 1 | Michael Clark 2 | C. Watford (christopher.watford@gmail.com) 3 | -------------------------------------------------------------------------------- /lib/json/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004, 2005 Metaparadigm Pte Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included 11 | in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/json/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/halayli/memqueue/1c04bc4b20d128ab7c0d0fc3d542a5f84bcb1ebf/lib/json/ChangeLog -------------------------------------------------------------------------------- /lib/json/INSTALL: -------------------------------------------------------------------------------- 1 | Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software 2 | Foundation, Inc. 3 | 4 | This file is free documentation; the Free Software Foundation gives 5 | unlimited permission to copy, distribute and modify it. 6 | 7 | Basic Installation 8 | ================== 9 | 10 | These are generic installation instructions. 11 | 12 | The `configure' shell script attempts to guess correct values for 13 | various system-dependent variables used during compilation. It uses 14 | those values to create a `Makefile' in each directory of the package. 15 | It may also create one or more `.h' files containing system-dependent 16 | definitions. Finally, it creates a shell script `config.status' that 17 | you can run in the future to recreate the current configuration, and a 18 | file `config.log' containing compiler output (useful mainly for 19 | debugging `configure'). 20 | 21 | It can also use an optional file (typically called `config.cache' 22 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 23 | the results of its tests to speed up reconfiguring. (Caching is 24 | disabled by default to prevent problems with accidental use of stale 25 | cache files.) 26 | 27 | If you need to do unusual things to compile the package, please try 28 | to figure out how `configure' could check whether to do them, and mail 29 | diffs or instructions to the address given in the `README' so they can 30 | be considered for the next release. If you are using the cache, and at 31 | some point `config.cache' contains results you don't want to keep, you 32 | may remove or edit it. 33 | 34 | The file `configure.ac' (or `configure.in') is used to create 35 | `configure' by a program called `autoconf'. You only need 36 | `configure.ac' if you want to change it or regenerate `configure' using 37 | a newer version of `autoconf'. 38 | 39 | The simplest way to compile this package is: 40 | 41 | 1. `cd' to the directory containing the package's source code and type 42 | `./configure' to configure the package for your system. If you're 43 | using `csh' on an old version of System V, you might need to type 44 | `sh ./configure' instead to prevent `csh' from trying to execute 45 | `configure' itself. 46 | 47 | Running `configure' takes awhile. While running, it prints some 48 | messages telling which features it is checking for. 49 | 50 | 2. Type `make' to compile the package. 51 | 52 | 3. Optionally, type `make check' to run any self-tests that come with 53 | the package. 54 | 55 | 4. Type `make install' to install the programs and any data files and 56 | documentation. 57 | 58 | 5. You can remove the program binaries and object files from the 59 | source code directory by typing `make clean'. To also remove the 60 | files that `configure' created (so you can compile the package for 61 | a different kind of computer), type `make distclean'. There is 62 | also a `make maintainer-clean' target, but that is intended mainly 63 | for the package's developers. If you use it, you may have to get 64 | all sorts of other programs in order to regenerate files that came 65 | with the distribution. 66 | 67 | Compilers and Options 68 | ===================== 69 | 70 | Some systems require unusual options for compilation or linking that 71 | the `configure' script does not know about. Run `./configure --help' 72 | for details on some of the pertinent environment variables. 73 | 74 | You can give `configure' initial values for configuration parameters 75 | by setting variables in the command line or in the environment. Here 76 | is an example: 77 | 78 | ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix 79 | 80 | *Note Defining Variables::, for more details. 81 | 82 | Compiling For Multiple Architectures 83 | ==================================== 84 | 85 | You can compile the package for more than one kind of computer at the 86 | same time, by placing the object files for each architecture in their 87 | own directory. To do this, you must use a version of `make' that 88 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 89 | directory where you want the object files and executables to go and run 90 | the `configure' script. `configure' automatically checks for the 91 | source code in the directory that `configure' is in and in `..'. 92 | 93 | If you have to use a `make' that does not support the `VPATH' 94 | variable, you have to compile the package for one architecture at a 95 | time in the source code directory. After you have installed the 96 | package for one architecture, use `make distclean' before reconfiguring 97 | for another architecture. 98 | 99 | Installation Names 100 | ================== 101 | 102 | By default, `make install' will install the package's files in 103 | `/usr/local/bin', `/usr/local/man', etc. You can specify an 104 | installation prefix other than `/usr/local' by giving `configure' the 105 | option `--prefix=PATH'. 106 | 107 | You can specify separate installation prefixes for 108 | architecture-specific files and architecture-independent files. If you 109 | give `configure' the option `--exec-prefix=PATH', the package will use 110 | PATH as the prefix for installing programs and libraries. 111 | Documentation and other data files will still use the regular prefix. 112 | 113 | In addition, if you use an unusual directory layout you can give 114 | options like `--bindir=PATH' to specify different values for particular 115 | kinds of files. Run `configure --help' for a list of the directories 116 | you can set and what kinds of files go in them. 117 | 118 | If the package supports it, you can cause programs to be installed 119 | with an extra prefix or suffix on their names by giving `configure' the 120 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 121 | 122 | Optional Features 123 | ================= 124 | 125 | Some packages pay attention to `--enable-FEATURE' options to 126 | `configure', where FEATURE indicates an optional part of the package. 127 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 128 | is something like `gnu-as' or `x' (for the X Window System). The 129 | `README' should mention any `--enable-' and `--with-' options that the 130 | package recognizes. 131 | 132 | For packages that use the X Window System, `configure' can usually 133 | find the X include and library files automatically, but if it doesn't, 134 | you can use the `configure' options `--x-includes=DIR' and 135 | `--x-libraries=DIR' to specify their locations. 136 | 137 | Specifying the System Type 138 | ========================== 139 | 140 | There may be some features `configure' cannot figure out 141 | automatically, but needs to determine by the type of machine the package 142 | will run on. Usually, assuming the package is built to be run on the 143 | _same_ architectures, `configure' can figure that out, but if it prints 144 | a message saying it cannot guess the machine type, give it the 145 | `--build=TYPE' option. TYPE can either be a short name for the system 146 | type, such as `sun4', or a canonical name which has the form: 147 | 148 | CPU-COMPANY-SYSTEM 149 | 150 | where SYSTEM can have one of these forms: 151 | 152 | OS KERNEL-OS 153 | 154 | See the file `config.sub' for the possible values of each field. If 155 | `config.sub' isn't included in this package, then this package doesn't 156 | need to know the machine type. 157 | 158 | If you are _building_ compiler tools for cross-compiling, you should 159 | use the `--target=TYPE' option to select the type of system they will 160 | produce code for. 161 | 162 | If you want to _use_ a cross compiler, that generates code for a 163 | platform different from the build platform, you should specify the 164 | "host" platform (i.e., that on which the generated programs will 165 | eventually be run) with `--host=TYPE'. 166 | 167 | Sharing Defaults 168 | ================ 169 | 170 | If you want to set default values for `configure' scripts to share, 171 | you can create a site shell script called `config.site' that gives 172 | default values for variables like `CC', `cache_file', and `prefix'. 173 | `configure' looks for `PREFIX/share/config.site' if it exists, then 174 | `PREFIX/etc/config.site' if it exists. Or, you can set the 175 | `CONFIG_SITE' environment variable to the location of the site script. 176 | A warning: not all `configure' scripts look for a site script. 177 | 178 | Defining Variables 179 | ================== 180 | 181 | Variables not defined in a site shell script can be set in the 182 | environment passed to `configure'. However, some packages may run 183 | configure again during the build, and the customized values of these 184 | variables may be lost. In order to avoid this problem, you should set 185 | them in the `configure' command line, using `VAR=value'. For example: 186 | 187 | ./configure CC=/usr/local2/bin/gcc 188 | 189 | will cause the specified gcc to be used as the C compiler (unless it is 190 | overridden in the site shell script). 191 | 192 | `configure' Invocation 193 | ====================== 194 | 195 | `configure' recognizes the following options to control how it 196 | operates. 197 | 198 | `--help' 199 | `-h' 200 | Print a summary of the options to `configure', and exit. 201 | 202 | `--version' 203 | `-V' 204 | Print the version of Autoconf used to generate the `configure' 205 | script, and exit. 206 | 207 | `--cache-file=FILE' 208 | Enable the cache: use and save the results of the tests in FILE, 209 | traditionally `config.cache'. FILE defaults to `/dev/null' to 210 | disable caching. 211 | 212 | `--config-cache' 213 | `-C' 214 | Alias for `--cache-file=config.cache'. 215 | 216 | `--quiet' 217 | `--silent' 218 | `-q' 219 | Do not print messages saying which checks are being made. To 220 | suppress all normal output, redirect it to `/dev/null' (any error 221 | messages will still be shown). 222 | 223 | `--srcdir=DIR' 224 | Look for the package's source code in directory DIR. Usually 225 | `configure' can determine that directory automatically. 226 | 227 | `configure' also accepts some other, not widely useful, options. Run 228 | `configure --help' for more details. 229 | 230 | -------------------------------------------------------------------------------- /lib/json/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CFLAGS = -Wall -Wwrite-strings -Werror -std=gnu99 -D_GNU_SOURCE -D_REENTRANT 2 | 3 | EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc 4 | 5 | lib_LTLIBRARIES = libjson.la 6 | 7 | pkgconfigdir = $(libdir)/pkgconfig 8 | pkgconfig_DATA = json.pc 9 | 10 | libjsonincludedir = $(includedir)/json 11 | libjsoninclude_HEADERS = \ 12 | json.h \ 13 | bits.h \ 14 | debug.h \ 15 | linkhash.h \ 16 | arraylist.h \ 17 | printbuf.h \ 18 | json_util.h \ 19 | json_object.h \ 20 | json_object_private.h \ 21 | json_tokener.h 22 | 23 | libjson_la_LDFLAGS = -version-info 0:1:0 24 | 25 | libjson_la_SOURCES = \ 26 | arraylist.c \ 27 | debug.c \ 28 | json_object.c \ 29 | json_tokener.c \ 30 | json_util.c \ 31 | linkhash.c \ 32 | printbuf.c 33 | 34 | check_PROGRAMS = test1 test2 test3 35 | 36 | test1_SOURCES = test1.c 37 | test1_LDADD = $(lib_LTLIBRARIES) 38 | 39 | test2_SOURCES = test2.c 40 | test2_LDADD = $(lib_LTLIBRARIES) 41 | 42 | test3_SOURCES = test3.c 43 | test3_LDADD = $(lib_LTLIBRARIES) 44 | -------------------------------------------------------------------------------- /lib/json/NEWS: -------------------------------------------------------------------------------- 1 | News 2 | -------------------------------------------------------------------------------- /lib/json/README: -------------------------------------------------------------------------------- 1 | Building on Unix with gcc and autotools 2 | 3 | If checking out from CVS: 4 | 5 | sh autogen.sh 6 | 7 | Then configure, make, make install 8 | 9 | 10 | Test programs 11 | 12 | To build the test programs run 'make check' 13 | 14 | 15 | Linking to libjson 16 | 17 | If your system has pkgconfig then you can just add this to your makefile 18 | 19 | CFLAGS += $(shell pkg-config --cflags json) 20 | LDFLAGS += $(shell pkg-config --libs json) 21 | -------------------------------------------------------------------------------- /lib/json/README-WIN32.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | JSON-C - A JSON implementation in C - Win32 specific notes 7 | 8 | 9 | 10 |

Windows specific notes for JSON-C

11 |

Please send Win32 bug reports to christopher.watford@gmail.com

12 |

Win32 Specific Changes:

13 |
    14 |
  • 15 | Various functions have been redefined to their Win32 version (i.e. open 16 | on win32 is _open)
  • 17 |
  • 18 | Implemented missing functions from MS's libc (i.e. vasprintf and strndup)
  • 19 |
  • 20 | Added code to allow Win64 support without integer resizing issues, this 21 | probably makes it much nicer on 64bit machines everywhere (i.e. using ptrdiff_t 22 | for pointer math)
  • 23 |
24 |

Porting Changelog:

25 |
26 |
printbuf.c - C. Watford (christopher.watford@gmail.com)
27 |
28 | Added a Win32/Win64 compliant implementation of vasprintf
29 |
debug.c - C. Watford (christopher.watford@gmail.com)
30 |
31 | Removed usage of vsyslog on Win32/Win64 systems, needs to be handled 32 | by a configure script
33 |
json_object.c - C. Watford (christopher.watford@gmail.com)
34 |
35 | Added scope operator to wrap usage of json_object_object_foreach, this needs to be 36 | rethought to be more ANSI C friendly
37 |
json_object.h - C. Watford (christopher.watford@gmail.com)
38 |
39 | Added Microsoft C friendly version of json_object_object_foreach
40 |
json_tokener.c - C. Watford (christopher.watford@gmail.com)
41 |
42 | Added a Win32/Win64 compliant implementation of strndup
43 |
json_util.c - C. Watford (christopher.watford@gmail.com)
44 |
45 | Added cast and mask to suffice size_t v. unsigned int 46 | conversion correctness
47 |
48 |

Anonymous Subversion

49 |

# svn co http://svn.metaparadigm.com/svn/json-c/trunk json-c

50 |

Copyright Metaparadigm Pte. Ltd. 2004, 2005. Michael 51 | Clark 52 |

53 |

This program is free software; you can redistribute it and/or modify it under 54 | the terms of the MIT License. See COPYING for details.

55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /lib/json/README.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | JSON-C - A JSON implementation in C 7 | 8 | 9 | 10 |

JSON-C - A JSON implementation in C

11 |

Latest release: json-c-0.9.tar.gz

12 |

JSON-C implements a reference counting object model that allows you to easily 13 | construct JSON objects in C, output them as JSON formatted strings and parse 14 | JSON formatted strings back into the C representation of JSON objects.

15 |

Minimal documentation exists here, 16 | Although you are probably better reading the example code in test1.c.

17 |

To setup JSON-C to build on your system please run configure before 18 | compiling. If you are on Win32 and are not using the VS project file, be sure 19 | to rename config.h.win32 to config.h before building.

20 |

Win32 specific notes can be found here.

21 |

Please send bug reports to michael@metaparadigm.com

22 |

Please send Win32 bug reports to christopher.watford@gmail.com

23 |

Anonymous Subversion

24 |

# svn co http://svn.metaparadigm.com/svn/json-c/trunk json-c

25 |

Copyright Metaparadigm Pte. Ltd. 2004, 2005. Michael 26 | Clark 27 |

28 |

This program is free software; you can redistribute it and/or modify it under 29 | the terms of the MIT License. See COPYING for details.

30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /lib/json/arraylist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | 14 | #if STDC_HEADERS 15 | # include 16 | # include 17 | #endif /* STDC_HEADERS */ 18 | 19 | #if defined HAVE_STRINGS_H && !defined _STRING_H && !defined __USE_BSD 20 | # include 21 | #endif /* HAVE_STRINGS_H */ 22 | 23 | #include "bits.h" 24 | #include "arraylist.h" 25 | 26 | struct array_list* 27 | array_list_new(array_list_free_fn *free_fn) 28 | { 29 | struct array_list *arr; 30 | 31 | arr = (struct array_list*)calloc(1, sizeof(struct array_list)); 32 | if(!arr) return NULL; 33 | arr->size = ARRAY_LIST_DEFAULT_SIZE; 34 | arr->length = 0; 35 | arr->free_fn = free_fn; 36 | if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { 37 | free(arr); 38 | return NULL; 39 | } 40 | return arr; 41 | } 42 | 43 | extern void 44 | array_list_free(struct array_list *arr) 45 | { 46 | int i; 47 | for(i = 0; i < arr->length; i++) 48 | if(arr->array[i]) arr->free_fn(arr->array[i]); 49 | free(arr->array); 50 | free(arr); 51 | } 52 | 53 | void* 54 | array_list_get_idx(struct array_list *arr, int i) 55 | { 56 | if(i >= arr->length) return NULL; 57 | return arr->array[i]; 58 | } 59 | 60 | static int array_list_expand_internal(struct array_list *arr, int max) 61 | { 62 | void *t; 63 | int new_size; 64 | 65 | if(max < arr->size) return 0; 66 | new_size = json_max(arr->size << 1, max); 67 | if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; 68 | arr->array = (void**)t; 69 | (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); 70 | arr->size = new_size; 71 | return 0; 72 | } 73 | 74 | int 75 | array_list_put_idx(struct array_list *arr, int idx, void *data) 76 | { 77 | if(array_list_expand_internal(arr, idx)) return -1; 78 | if(arr->array[idx]) arr->free_fn(arr->array[idx]); 79 | arr->array[idx] = data; 80 | if(arr->length <= idx) arr->length = idx + 1; 81 | return 0; 82 | } 83 | 84 | int 85 | array_list_add(struct array_list *arr, void *data) 86 | { 87 | return array_list_put_idx(arr, arr->length, data); 88 | } 89 | 90 | int 91 | array_list_length(struct array_list *arr) 92 | { 93 | return arr->length; 94 | } 95 | -------------------------------------------------------------------------------- /lib/json/arraylist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _arraylist_h_ 13 | #define _arraylist_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define ARRAY_LIST_DEFAULT_SIZE 32 20 | 21 | typedef void (array_list_free_fn) (void *data); 22 | 23 | struct array_list 24 | { 25 | void **array; 26 | int length; 27 | int size; 28 | array_list_free_fn *free_fn; 29 | }; 30 | 31 | extern struct array_list* 32 | array_list_new(array_list_free_fn *free_fn); 33 | 34 | extern void 35 | array_list_free(struct array_list *al); 36 | 37 | extern void* 38 | array_list_get_idx(struct array_list *al, int i); 39 | 40 | extern int 41 | array_list_put_idx(struct array_list *al, int i, void *data); 42 | 43 | extern int 44 | array_list_add(struct array_list *al, void *data); 45 | 46 | extern int 47 | array_list_length(struct array_list *al); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /lib/json/bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _bits_h_ 13 | #define _bits_h_ 14 | 15 | #ifndef json_min 16 | #define json_min(a,b) ((a) < (b) ? (a) : (b)) 17 | #endif 18 | 19 | #ifndef json_max 20 | #define json_max(a,b) ((a) > (b) ? (a) : (b)) 21 | #endif 22 | 23 | #define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) 24 | #define error_ptr(error) ((void*)error) 25 | #define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /lib/json/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.in by autoheader. */ 3 | 4 | /* Define to 1 if you have the header file. */ 5 | #define HAVE_DLFCN_H 1 6 | 7 | /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ 8 | /* #undef HAVE_DOPRNT */ 9 | 10 | /* Define to 1 if you have the header file. */ 11 | #define HAVE_FCNTL_H 1 12 | 13 | /* Define to 1 if you have the header file. */ 14 | #define HAVE_INTTYPES_H 1 15 | 16 | /* Define to 1 if you have the header file. */ 17 | #define HAVE_LIMITS_H 1 18 | 19 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 20 | to 0 otherwise. */ 21 | #define HAVE_MALLOC 1 22 | 23 | /* Define to 1 if you have the header file. */ 24 | #define HAVE_MEMORY_H 1 25 | 26 | /* Define to 1 if you have the `open' function. */ 27 | #define HAVE_OPEN 1 28 | 29 | /* Define to 1 if your system has a GNU libc compatible `realloc' function, 30 | and to 0 otherwise. */ 31 | #define HAVE_REALLOC 1 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #define HAVE_STDARG_H 1 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #define HAVE_STDINT_H 1 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #define HAVE_STDLIB_H 1 41 | 42 | /* Define to 1 if you have the `strerror' function. */ 43 | #define HAVE_STRERROR 1 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #define HAVE_STRINGS_H 1 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #define HAVE_STRING_H 1 50 | 51 | /* Define to 1 if you have the `strncasecmp' function. */ 52 | #define HAVE_STRNCASECMP 1 53 | 54 | /* Define to 1 if you have the `strndup' function. */ 55 | #define HAVE_STRNDUP 1 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #define HAVE_SYSLOG_H 1 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #define HAVE_SYS_PARAM_H 1 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #define HAVE_SYS_STAT_H 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_SYS_TYPES_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #define HAVE_UNISTD_H 1 71 | 72 | /* Define to 1 if you have the `vasprintf' function. */ 73 | #define HAVE_VASPRINTF 1 74 | 75 | /* Define to 1 if you have the `vprintf' function. */ 76 | #define HAVE_VPRINTF 1 77 | 78 | /* Define to 1 if you have the `vsnprintf' function. */ 79 | #define HAVE_VSNPRINTF 1 80 | 81 | /* Define to 1 if you have the `vsyslog' function. */ 82 | #define HAVE_VSYSLOG 1 83 | 84 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 85 | */ 86 | #define LT_OBJDIR ".libs/" 87 | 88 | /* Name of package */ 89 | #define PACKAGE "json-c" 90 | 91 | /* Define to the address where bug reports for this package should be sent. */ 92 | #define PACKAGE_BUGREPORT "michael@metaparadigm.com" 93 | 94 | /* Define to the full name of this package. */ 95 | #define PACKAGE_NAME "json-c" 96 | 97 | /* Define to the full name and version of this package. */ 98 | #define PACKAGE_STRING "json-c 0.9" 99 | 100 | /* Define to the one symbol short name of this package. */ 101 | #define PACKAGE_TARNAME "json-c" 102 | 103 | /* Define to the version of this package. */ 104 | #define PACKAGE_VERSION "0.9" 105 | 106 | /* Define to 1 if you have the ANSI C header files. */ 107 | #define STDC_HEADERS 1 108 | 109 | /* Version number of package */ 110 | #define VERSION "0.9" 111 | 112 | /* Define to empty if `const' does not conform to ANSI C. */ 113 | /* #undef const */ 114 | 115 | /* Define to rpl_malloc if the replacement function should be used. */ 116 | /* #undef malloc */ 117 | 118 | /* Define to rpl_realloc if the replacement function should be used. */ 119 | /* #undef realloc */ 120 | 121 | /* Define to `unsigned int' if does not define. */ 122 | /* #undef size_t */ 123 | -------------------------------------------------------------------------------- /lib/json/config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.in by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_DLFCN_H 5 | 6 | /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ 7 | #undef HAVE_DOPRNT 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_FCNTL_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_INTTYPES_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_LIMITS_H 17 | 18 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 19 | to 0 otherwise. */ 20 | #undef HAVE_MALLOC 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #undef HAVE_MEMORY_H 24 | 25 | /* Define to 1 if you have the `open' function. */ 26 | #undef HAVE_OPEN 27 | 28 | /* Define to 1 if your system has a GNU libc compatible `realloc' function, 29 | and to 0 otherwise. */ 30 | #undef HAVE_REALLOC 31 | 32 | /* Define to 1 if you have the header file. */ 33 | #undef HAVE_STDARG_H 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #undef HAVE_STDINT_H 37 | 38 | /* Define to 1 if you have the header file. */ 39 | #undef HAVE_STDLIB_H 40 | 41 | /* Define to 1 if you have the `strerror' function. */ 42 | #undef HAVE_STRERROR 43 | 44 | /* Define to 1 if you have the header file. */ 45 | #undef HAVE_STRINGS_H 46 | 47 | /* Define to 1 if you have the header file. */ 48 | #undef HAVE_STRING_H 49 | 50 | /* Define to 1 if you have the `strncasecmp' function. */ 51 | #undef HAVE_STRNCASECMP 52 | 53 | /* Define to 1 if you have the `strndup' function. */ 54 | #undef HAVE_STRNDUP 55 | 56 | /* Define to 1 if you have the header file. */ 57 | #undef HAVE_SYSLOG_H 58 | 59 | /* Define to 1 if you have the header file. */ 60 | #undef HAVE_SYS_PARAM_H 61 | 62 | /* Define to 1 if you have the header file. */ 63 | #undef HAVE_SYS_STAT_H 64 | 65 | /* Define to 1 if you have the header file. */ 66 | #undef HAVE_SYS_TYPES_H 67 | 68 | /* Define to 1 if you have the header file. */ 69 | #undef HAVE_UNISTD_H 70 | 71 | /* Define to 1 if you have the `vasprintf' function. */ 72 | #undef HAVE_VASPRINTF 73 | 74 | /* Define to 1 if you have the `vprintf' function. */ 75 | #undef HAVE_VPRINTF 76 | 77 | /* Define to 1 if you have the `vsnprintf' function. */ 78 | #undef HAVE_VSNPRINTF 79 | 80 | /* Define to 1 if you have the `vsyslog' function. */ 81 | #undef HAVE_VSYSLOG 82 | 83 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 84 | */ 85 | #undef LT_OBJDIR 86 | 87 | /* Name of package */ 88 | #undef PACKAGE 89 | 90 | /* Define to the address where bug reports for this package should be sent. */ 91 | #undef PACKAGE_BUGREPORT 92 | 93 | /* Define to the full name of this package. */ 94 | #undef PACKAGE_NAME 95 | 96 | /* Define to the full name and version of this package. */ 97 | #undef PACKAGE_STRING 98 | 99 | /* Define to the one symbol short name of this package. */ 100 | #undef PACKAGE_TARNAME 101 | 102 | /* Define to the version of this package. */ 103 | #undef PACKAGE_VERSION 104 | 105 | /* Define to 1 if you have the ANSI C header files. */ 106 | #undef STDC_HEADERS 107 | 108 | /* Version number of package */ 109 | #undef VERSION 110 | 111 | /* Define to empty if `const' does not conform to ANSI C. */ 112 | #undef const 113 | 114 | /* Define to rpl_malloc if the replacement function should be used. */ 115 | #undef malloc 116 | 117 | /* Define to rpl_realloc if the replacement function should be used. */ 118 | #undef realloc 119 | 120 | /* Define to `unsigned int' if does not define. */ 121 | #undef size_t 122 | -------------------------------------------------------------------------------- /lib/json/config.h.win32: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: config.h.win32,v 1.2 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | /* config.h.win32 Generated by configure. */ 13 | 14 | #define PACKAGE_STRING "JSON C Library 0.2" 15 | #define PACKAGE_BUGREPORT "michael@metaparadigm.com" 16 | #define PACKAGE_NAME "JSON C Library" 17 | #define PACKAGE_TARNAME "json-c" 18 | #define PACKAGE_VERSION "0.2" 19 | 20 | /* config.h.in. Generated from configure.ac by autoheader. */ 21 | 22 | /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ 23 | /* #undef HAVE_DOPRNT */ 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_FCNTL_H 1 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_INTTYPES_H 1 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #define HAVE_LIMITS_H 1 33 | 34 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 35 | to 0 otherwise. */ 36 | #define HAVE_MALLOC 1 37 | 38 | /* Define to 1 if you have the header file. */ 39 | #define HAVE_MEMORY_H 1 40 | 41 | /* Define to 1 if you have the `open' function. */ 42 | #undef HAVE_OPEN 43 | 44 | /* Define to 1 if your system has a GNU libc compatible `realloc' function, 45 | and to 0 otherwise. */ 46 | #define HAVE_REALLOC 1 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #define HAVE_STDINT_H 1 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #define HAVE_STDLIB_H 1 53 | 54 | /* Define to 1 if you have the `strdup' function. */ 55 | #undef HAVE_STRNDUP 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #define HAVE_STDARG_H 1 59 | 60 | /* Define to 1 if you have the `strerror' function. */ 61 | #define HAVE_STRERROR 1 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_STRINGS_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_STRING_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYSLOG_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_SYS_PARAM_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #define HAVE_SYS_STAT_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #define HAVE_SYS_TYPES_H 1 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_UNISTD_H 83 | 84 | /* Define to 1 if you have the `vprintf' function. */ 85 | #undef HAVE_VPRINTF 86 | 87 | /* Define to 1 if you have the `vsyslog' function. */ 88 | #undef HAVE_VSYSLOG 89 | 90 | /* Define to 1 if you have the `strncasecmp' function. */ 91 | #undef HAVE_STRNCASECMP 92 | 93 | /* Define to 1 if you have the ANSI C header files. */ 94 | #define STDC_HEADERS 1 95 | -------------------------------------------------------------------------------- /lib/json/configure.in: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.52) 2 | 3 | # Process this file with autoconf to produce a configure script. 4 | AC_INIT([json-c], 0.9, [michael@metaparadigm.com]) 5 | 6 | AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) 7 | 8 | # Checks for programs. 9 | 10 | # Checks for libraries. 11 | 12 | # Checks for header files. 13 | AM_CONFIG_HEADER(config.h) 14 | AC_HEADER_STDC 15 | AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/param.h] stdarg.h) 16 | 17 | # Checks for typedefs, structures, and compiler characteristics. 18 | AC_C_CONST 19 | AC_TYPE_SIZE_T 20 | 21 | # Checks for library functions. 22 | AC_FUNC_VPRINTF 23 | AC_FUNC_MEMCMP 24 | AC_FUNC_MALLOC 25 | AC_FUNC_REALLOC 26 | AC_CHECK_FUNCS(strndup strerror vsnprintf vasprintf open vsyslog strncasecmp) 27 | 28 | AM_PROG_LIBTOOL 29 | 30 | AC_OUTPUT([ 31 | Makefile 32 | json.pc 33 | ]) 34 | -------------------------------------------------------------------------------- /lib/json/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #if HAVE_SYSLOG_H 20 | # include 21 | #endif /* HAVE_SYSLOG_H */ 22 | 23 | #if HAVE_UNISTD_H 24 | # include 25 | #endif /* HAVE_UNISTD_H */ 26 | 27 | #if HAVE_SYS_PARAM_H 28 | #include 29 | #endif /* HAVE_SYS_PARAM_H */ 30 | 31 | #include "debug.h" 32 | 33 | static int _syslog = 0; 34 | static int _debug = 0; 35 | 36 | void mc_set_debug(int debug) { _debug = debug; } 37 | int mc_get_debug(void) { return _debug; } 38 | 39 | extern void mc_set_syslog(int syslog) 40 | { 41 | _syslog = syslog; 42 | } 43 | 44 | void mc_abort(const char *msg, ...) 45 | { 46 | va_list ap; 47 | va_start(ap, msg); 48 | #if HAVE_VSYSLOG 49 | if(_syslog) { 50 | vsyslog(LOG_ERR, msg, ap); 51 | } else 52 | #endif 53 | vprintf(msg, ap); 54 | va_end(ap); 55 | exit(1); 56 | } 57 | 58 | 59 | void mc_debug(const char *msg, ...) 60 | { 61 | va_list ap; 62 | if(_debug) { 63 | va_start(ap, msg); 64 | #if HAVE_VSYSLOG 65 | if(_syslog) { 66 | vsyslog(LOG_DEBUG, msg, ap); 67 | } else 68 | #endif 69 | vprintf(msg, ap); 70 | va_end(ap); 71 | } 72 | } 73 | 74 | void mc_error(const char *msg, ...) 75 | { 76 | va_list ap; 77 | va_start(ap, msg); 78 | #if HAVE_VSYSLOG 79 | if(_syslog) { 80 | vsyslog(LOG_ERR, msg, ap); 81 | } else 82 | #endif 83 | vfprintf(stderr, msg, ap); 84 | va_end(ap); 85 | } 86 | 87 | void mc_info(const char *msg, ...) 88 | { 89 | va_list ap; 90 | va_start(ap, msg); 91 | #if HAVE_VSYSLOG 92 | if(_syslog) { 93 | vsyslog(LOG_INFO, msg, ap); 94 | } else 95 | #endif 96 | vfprintf(stderr, msg, ap); 97 | va_end(ap); 98 | } 99 | -------------------------------------------------------------------------------- /lib/json/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _DEBUG_H_ 13 | #define _DEBUG_H_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | extern void mc_set_debug(int debug); 20 | extern int mc_get_debug(void); 21 | 22 | extern void mc_set_syslog(int syslog); 23 | extern void mc_abort(const char *msg, ...); 24 | extern void mc_debug(const char *msg, ...); 25 | extern void mc_error(const char *msg, ...); 26 | extern void mc_info(const char *msg, ...); 27 | 28 | #ifdef MC_MAINTAINER_MODE 29 | #define MC_SET_DEBUG(x) mc_set_debug(x) 30 | #define MC_GET_DEBUG() mc_get_debug() 31 | #define MC_SET_SYSLOG(x) mc_set_syslog(x) 32 | #define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__) 33 | #define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) 34 | #define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__) 35 | #define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) 36 | #else 37 | #define MC_SET_DEBUG(x) if (0) mc_set_debug(x) 38 | #define MC_GET_DEBUG() (0) 39 | #define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) 40 | #define MC_ABORT(x, ...) if (0) mc_abort(x, ##__VA_ARGS__) 41 | #define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) 42 | #define MC_ERROR(x, ...) if (0) mc_error(x, ##__VA_ARGS__) 43 | #define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) 44 | #endif 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /lib/json/json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_h_ 13 | #define _json_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #include "bits.h" 20 | #include "debug.h" 21 | #include "linkhash.h" 22 | #include "arraylist.h" 23 | #include "json_util.h" 24 | #include "json_object.h" 25 | #include "json_tokener.h" 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /lib/json/json.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr/local 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: json 7 | Description: JSON implementation in C 8 | Version: 0.9 9 | Requires: 10 | Libs: -L${libdir} -ljson 11 | Cflags: -I${includedir}/json 12 | -------------------------------------------------------------------------------- /lib/json/json.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: json 7 | Description: JSON implementation in C 8 | Version: @VERSION@ 9 | Requires: 10 | Libs: -L${libdir} -ljson 11 | Cflags: -I${includedir}/json 12 | -------------------------------------------------------------------------------- /lib/json/json_object.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_object_h_ 13 | #define _json_object_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define JSON_OBJECT_DEF_HASH_ENTRIES 16 20 | 21 | #undef FALSE 22 | #define FALSE ((boolean)0) 23 | 24 | #undef TRUE 25 | #define TRUE ((boolean)1) 26 | 27 | extern const char *json_number_chars; 28 | extern const char *json_hex_chars; 29 | 30 | /* forward structure definitions */ 31 | 32 | typedef int boolean; 33 | typedef struct printbuf printbuf; 34 | typedef struct lh_table lh_table; 35 | typedef struct array_list array_list; 36 | typedef struct json_object json_object; 37 | typedef struct json_object_iter json_object_iter; 38 | typedef struct json_tokener json_tokener; 39 | 40 | /* supported object types */ 41 | 42 | typedef enum json_type { 43 | json_type_null, 44 | json_type_boolean, 45 | json_type_double, 46 | json_type_int, 47 | json_type_object, 48 | json_type_array, 49 | json_type_string 50 | } json_type; 51 | 52 | /* reference counting functions */ 53 | 54 | /** 55 | * Increment the reference count of json_object 56 | * @param obj the json_object instance 57 | */ 58 | extern struct json_object* json_object_get(struct json_object *obj); 59 | 60 | /** 61 | * Decrement the reference count of json_object and free if it reaches zero 62 | * @param obj the json_object instance 63 | */ 64 | extern void json_object_put(struct json_object *obj); 65 | 66 | 67 | /** 68 | * Check if the json_object is of a given type 69 | * @param obj the json_object instance 70 | * @param type one of: 71 | json_type_boolean, 72 | json_type_double, 73 | json_type_int, 74 | json_type_object, 75 | json_type_array, 76 | json_type_string, 77 | */ 78 | extern int json_object_is_type(struct json_object *obj, enum json_type type); 79 | 80 | /** 81 | * Get the type of the json_object 82 | * @param obj the json_object instance 83 | * @returns type being one of: 84 | json_type_boolean, 85 | json_type_double, 86 | json_type_int, 87 | json_type_object, 88 | json_type_array, 89 | json_type_string, 90 | */ 91 | extern enum json_type json_object_get_type(struct json_object *obj); 92 | 93 | 94 | /** Stringify object to json format 95 | * @param obj the json_object instance 96 | * @returns a string in JSON format 97 | */ 98 | extern const char* json_object_to_json_string(struct json_object *obj); 99 | 100 | 101 | /* object type methods */ 102 | 103 | /** Create a new empty object 104 | * @returns a json_object of type json_type_object 105 | */ 106 | extern struct json_object* json_object_new_object(void); 107 | 108 | /** Get the hashtable of a json_object of type json_type_object 109 | * @param obj the json_object instance 110 | * @returns a linkhash 111 | */ 112 | extern struct lh_table* json_object_get_object(struct json_object *obj); 113 | 114 | /** Add an object field to a json_object of type json_type_object 115 | * 116 | * The reference count will *not* be incremented. This is to make adding 117 | * fields to objects in code more compact. If you want to retain a reference 118 | * to an added object you must wrap the passed object with json_object_get 119 | * 120 | * @param obj the json_object instance 121 | * @param key the object field name (a private copy will be duplicated) 122 | * @param val a json_object or NULL member to associate with the given field 123 | */ 124 | extern void json_object_object_add(struct json_object* obj, const char *key, 125 | struct json_object *val); 126 | 127 | /** Get the json_object associate with a given object field 128 | * @param obj the json_object instance 129 | * @param key the object field name 130 | * @returns the json_object associated with the given field name 131 | */ 132 | extern struct json_object* json_object_object_get(struct json_object* obj, 133 | const char *key); 134 | 135 | /** Delete the given json_object field 136 | * 137 | * The reference count will be decremented for the deleted object 138 | * 139 | * @param obj the json_object instance 140 | * @param key the object field name 141 | */ 142 | extern void json_object_object_del(struct json_object* obj, const char *key); 143 | 144 | /** Iterate through all keys and values of an object 145 | * @param obj the json_object instance 146 | * @param key the local name for the char* key variable defined in the body 147 | * @param val the local name for the json_object* object variable defined in the body 148 | */ 149 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) 150 | 151 | # define json_object_object_foreach(obj,key,val) \ 152 | char *key; struct json_object *val; \ 153 | for(struct lh_entry *entry = json_object_get_object(obj)->head; ({ if(entry) { key = (char*)entry->k; val = (struct json_object*)entry->v; } ; entry; }); entry = entry->next ) 154 | 155 | #else /* ANSI C or MSC */ 156 | 157 | # define json_object_object_foreach(obj,key,val) \ 158 | char *key; struct json_object *val; struct lh_entry *entry; \ 159 | for(entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, val = (struct json_object*)entry->v, entry) : 0); entry = entry->next) 160 | 161 | #endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */ 162 | 163 | /** Iterate through all keys and values of an object (ANSI C Safe) 164 | * @param obj the json_object instance 165 | * @param iter the object iterator 166 | */ 167 | #define json_object_object_foreachC(obj,iter) \ 168 | for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next) 169 | 170 | /* Array type methods */ 171 | 172 | /** Create a new empty json_object of type json_type_array 173 | * @returns a json_object of type json_type_array 174 | */ 175 | extern struct json_object* json_object_new_array(void); 176 | 177 | /** Get the arraylist of a json_object of type json_type_array 178 | * @param obj the json_object instance 179 | * @returns an arraylist 180 | */ 181 | extern struct array_list* json_object_get_array(struct json_object *obj); 182 | 183 | /** Get the length of a json_object of type json_type_array 184 | * @param obj the json_object instance 185 | * @returns an int 186 | */ 187 | extern int json_object_array_length(struct json_object *obj); 188 | 189 | /** Add an element to the end of a json_object of type json_type_array 190 | * 191 | * The reference count will *not* be incremented. This is to make adding 192 | * fields to objects in code more compact. If you want to retain a reference 193 | * to an added object you must wrap the passed object with json_object_get 194 | * 195 | * @param obj the json_object instance 196 | * @param val the json_object to be added 197 | */ 198 | extern int json_object_array_add(struct json_object *obj, 199 | struct json_object *val); 200 | 201 | /** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) 202 | * 203 | * The reference count will *not* be incremented. This is to make adding 204 | * fields to objects in code more compact. If you want to retain a reference 205 | * to an added object you must wrap the passed object with json_object_get 206 | * 207 | * The reference count of a replaced object will be decremented. 208 | * 209 | * The array size will be automatically be expanded to the size of the 210 | * index if the index is larger than the current size. 211 | * 212 | * @param obj the json_object instance 213 | * @param idx the index to insert the element at 214 | * @param val the json_object to be added 215 | */ 216 | extern int json_object_array_put_idx(struct json_object *obj, int idx, 217 | struct json_object *val); 218 | 219 | /** Get the element at specificed index of the array (a json_object of type json_type_array) 220 | * @param obj the json_object instance 221 | * @param idx the index to get the element at 222 | * @returns the json_object at the specified index (or NULL) 223 | */ 224 | extern struct json_object* json_object_array_get_idx(struct json_object *obj, 225 | int idx); 226 | 227 | /* boolean type methods */ 228 | 229 | /** Create a new empty json_object of type json_type_boolean 230 | * @param b a boolean TRUE or FALSE (0 or 1) 231 | * @returns a json_object of type json_type_boolean 232 | */ 233 | extern struct json_object* json_object_new_boolean(boolean b); 234 | 235 | /** Get the boolean value of a json_object 236 | * 237 | * The type is coerced to a boolean if the passed object is not a boolean. 238 | * integer and double objects will return FALSE if there value is zero 239 | * or TRUE otherwise. If the passed object is a string it will return 240 | * TRUE if it has a non zero length. If any other object type is passed 241 | * TRUE will be returned if the object is not NULL. 242 | * 243 | * @param obj the json_object instance 244 | * @returns a boolean 245 | */ 246 | extern boolean json_object_get_boolean(struct json_object *obj); 247 | 248 | 249 | /* int type methods */ 250 | 251 | /** Create a new empty json_object of type json_type_int 252 | * @param i the integer 253 | * @returns a json_object of type json_type_int 254 | */ 255 | extern struct json_object* json_object_new_int(int i); 256 | 257 | /** Get the int value of a json_object 258 | * 259 | * The type is coerced to a int if the passed object is not a int. 260 | * double objects will return their integer conversion. Strings will be 261 | * parsed as an integer. If no conversion exists then 0 is returned. 262 | * 263 | * @param obj the json_object instance 264 | * @returns an int 265 | */ 266 | extern int json_object_get_int(struct json_object *obj); 267 | 268 | 269 | /* double type methods */ 270 | 271 | /** Create a new empty json_object of type json_type_double 272 | * @param d the double 273 | * @returns a json_object of type json_type_double 274 | */ 275 | extern struct json_object* json_object_new_double(double d); 276 | 277 | /** Get the double value of a json_object 278 | * 279 | * The type is coerced to a double if the passed object is not a double. 280 | * integer objects will return their dboule conversion. Strings will be 281 | * parsed as a double. If no conversion exists then 0.0 is returned. 282 | * 283 | * @param obj the json_object instance 284 | * @returns an double 285 | */ 286 | extern double json_object_get_double(struct json_object *obj); 287 | 288 | 289 | /* string type methods */ 290 | 291 | /** Create a new empty json_object of type json_type_string 292 | * 293 | * A copy of the string is made and the memory is managed by the json_object 294 | * 295 | * @param s the string 296 | * @returns a json_object of type json_type_string 297 | */ 298 | extern struct json_object* json_object_new_string(const char *s); 299 | 300 | extern struct json_object* json_object_new_string_len(const char *s, int len); 301 | 302 | /** Get the string value of a json_object 303 | * 304 | * If the passed object is not of type json_type_string then the JSON 305 | * representation of the object is returned. 306 | * 307 | * The returned string memory is managed by the json_object and will 308 | * be freed when the reference count of the json_object drops to zero. 309 | * 310 | * @param obj the json_object instance 311 | * @returns a string 312 | */ 313 | extern const char* json_object_get_string(struct json_object *obj); 314 | 315 | #ifdef __cplusplus 316 | } 317 | #endif 318 | 319 | #endif 320 | -------------------------------------------------------------------------------- /lib/json/json_object_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_object_private_h_ 13 | #define _json_object_private_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | typedef void (json_object_delete_fn)(struct json_object *o); 20 | typedef int (json_object_to_json_string_fn)(struct json_object *o, 21 | struct printbuf *pb); 22 | 23 | struct json_object 24 | { 25 | enum json_type o_type; 26 | json_object_delete_fn *_delete; 27 | json_object_to_json_string_fn *_to_json_string; 28 | int _ref_count; 29 | struct printbuf *_pb; 30 | union data { 31 | boolean c_boolean; 32 | double c_double; 33 | int c_int; 34 | struct lh_table *c_object; 35 | struct array_list *c_array; 36 | char *c_string; 37 | } o; 38 | }; 39 | 40 | /* CAW: added for ANSI C iteration correctness */ 41 | struct json_object_iter 42 | { 43 | char *key; 44 | struct json_object *val; 45 | struct lh_entry *entry; 46 | }; 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /lib/json/json_tokener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_tokener_h_ 13 | #define _json_tokener_h_ 14 | 15 | #include 16 | #include "json_object.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | enum json_tokener_error { 23 | json_tokener_success, 24 | json_tokener_continue, 25 | json_tokener_error_depth, 26 | json_tokener_error_parse_eof, 27 | json_tokener_error_parse_unexpected, 28 | json_tokener_error_parse_null, 29 | json_tokener_error_parse_boolean, 30 | json_tokener_error_parse_number, 31 | json_tokener_error_parse_array, 32 | json_tokener_error_parse_object_key_name, 33 | json_tokener_error_parse_object_key_sep, 34 | json_tokener_error_parse_object_value_sep, 35 | json_tokener_error_parse_string, 36 | json_tokener_error_parse_comment 37 | }; 38 | 39 | enum json_tokener_state { 40 | json_tokener_state_eatws, 41 | json_tokener_state_start, 42 | json_tokener_state_finish, 43 | json_tokener_state_null, 44 | json_tokener_state_comment_start, 45 | json_tokener_state_comment, 46 | json_tokener_state_comment_eol, 47 | json_tokener_state_comment_end, 48 | json_tokener_state_string, 49 | json_tokener_state_string_escape, 50 | json_tokener_state_escape_unicode, 51 | json_tokener_state_boolean, 52 | json_tokener_state_number, 53 | json_tokener_state_array, 54 | json_tokener_state_array_add, 55 | json_tokener_state_array_sep, 56 | json_tokener_state_object_field_start, 57 | json_tokener_state_object_field, 58 | json_tokener_state_object_field_end, 59 | json_tokener_state_object_value, 60 | json_tokener_state_object_value_add, 61 | json_tokener_state_object_sep 62 | }; 63 | 64 | struct json_tokener_srec 65 | { 66 | enum json_tokener_state state, saved_state; 67 | struct json_object *obj; 68 | struct json_object *current; 69 | char *obj_field_name; 70 | }; 71 | 72 | #define JSON_TOKENER_MAX_DEPTH 32 73 | 74 | struct json_tokener 75 | { 76 | char *str; 77 | struct printbuf *pb; 78 | int depth, is_double, st_pos, char_offset; 79 | ptrdiff_t err; 80 | unsigned int ucs_char; 81 | char quote_char; 82 | struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH]; 83 | }; 84 | 85 | extern const char* json_tokener_errors[]; 86 | 87 | extern struct json_tokener* json_tokener_new(void); 88 | extern void json_tokener_free(struct json_tokener *tok); 89 | extern void json_tokener_reset(struct json_tokener *tok); 90 | extern struct json_object* json_tokener_parse(const char *str); 91 | extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok, 92 | const char *str, int len); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /lib/json/json_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #if HAVE_SYS_TYPES_H 22 | #include 23 | #endif /* HAVE_SYS_TYPES_H */ 24 | 25 | #if HAVE_SYS_STAT_H 26 | #include 27 | #endif /* HAVE_SYS_STAT_H */ 28 | 29 | #if HAVE_FCNTL_H 30 | #include 31 | #endif /* HAVE_FCNTL_H */ 32 | 33 | #if HAVE_UNISTD_H 34 | # include 35 | #endif /* HAVE_UNISTD_H */ 36 | 37 | #ifdef WIN32 38 | # define WIN32_LEAN_AND_MEAN 39 | # include 40 | # include 41 | #endif /* defined(WIN32) */ 42 | 43 | #if !HAVE_OPEN && defined(WIN32) 44 | # define open _open 45 | #endif 46 | 47 | 48 | #include "bits.h" 49 | #include "debug.h" 50 | #include "printbuf.h" 51 | #include "json_object.h" 52 | #include "json_tokener.h" 53 | #include "json_util.h" 54 | 55 | struct json_object* json_object_from_file(char *filename) 56 | { 57 | struct printbuf *pb; 58 | struct json_object *obj; 59 | char buf[JSON_FILE_BUF_SIZE]; 60 | int fd, ret; 61 | 62 | if((fd = open(filename, O_RDONLY)) < 0) { 63 | MC_ERROR("json_object_from_file: error reading file %s: %s\n", 64 | filename, strerror(errno)); 65 | return (struct json_object*)error_ptr(-1); 66 | } 67 | if(!(pb = printbuf_new())) { 68 | MC_ERROR("json_object_from_file: printbuf_new failed\n"); 69 | return (struct json_object*)error_ptr(-1); 70 | } 71 | while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { 72 | printbuf_memappend(pb, buf, ret); 73 | } 74 | close(fd); 75 | if(ret < 0) { 76 | MC_ABORT("json_object_from_file: error reading file %s: %s\n", 77 | filename, strerror(errno)); 78 | printbuf_free(pb); 79 | return (struct json_object*)error_ptr(-1); 80 | } 81 | obj = json_tokener_parse(pb->buf); 82 | printbuf_free(pb); 83 | return obj; 84 | } 85 | 86 | int json_object_to_file(char *filename, struct json_object *obj) 87 | { 88 | const char *json_str; 89 | int fd, ret; 90 | unsigned int wpos, wsize; 91 | 92 | if(!obj) { 93 | MC_ERROR("json_object_to_file: object is null\n"); 94 | return -1; 95 | } 96 | 97 | if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { 98 | MC_ERROR("json_object_to_file: error opening file %s: %s\n", 99 | filename, strerror(errno)); 100 | return -1; 101 | } 102 | 103 | if(!(json_str = json_object_to_json_string(obj))) { return -1; } 104 | 105 | 106 | wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ 107 | wpos = 0; 108 | while(wpos < wsize) { 109 | if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { 110 | close(fd); 111 | MC_ERROR("json_object_to_file: error writing file %s: %s\n", 112 | filename, strerror(errno)); 113 | return -1; 114 | } 115 | 116 | /* because of the above check for ret < 0, we can safely cast and add */ 117 | wpos += (unsigned int)ret; 118 | } 119 | 120 | close(fd); 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /lib/json/json_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_util_h_ 13 | #define _json_util_h_ 14 | 15 | #include "json_object.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #define JSON_FILE_BUF_SIZE 4096 22 | 23 | /* utility functions */ 24 | extern struct json_object* json_object_from_file(char *filename); 25 | extern int json_object_to_file(char *filename, struct json_object *obj); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /lib/json/linkhash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "linkhash.h" 20 | 21 | void lh_abort(const char *msg, ...) 22 | { 23 | va_list ap; 24 | va_start(ap, msg); 25 | vprintf(msg, ap); 26 | va_end(ap); 27 | exit(1); 28 | } 29 | 30 | unsigned long lh_ptr_hash(const void *k) 31 | { 32 | /* CAW: refactored to be 64bit nice */ 33 | return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX); 34 | } 35 | 36 | int lh_ptr_equal(const void *k1, const void *k2) 37 | { 38 | return (k1 == k2); 39 | } 40 | 41 | unsigned long lh_char_hash(const void *k) 42 | { 43 | unsigned int h = 0; 44 | const char* data = (const char*)k; 45 | 46 | while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME; 47 | 48 | return h; 49 | } 50 | 51 | int lh_char_equal(const void *k1, const void *k2) 52 | { 53 | return (strcmp((const char*)k1, (const char*)k2) == 0); 54 | } 55 | 56 | struct lh_table* lh_table_new(int size, const char *name, 57 | lh_entry_free_fn *free_fn, 58 | lh_hash_fn *hash_fn, 59 | lh_equal_fn *equal_fn) 60 | { 61 | int i; 62 | struct lh_table *t; 63 | 64 | t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); 65 | if(!t) lh_abort("lh_table_new: calloc failed\n"); 66 | t->count = 0; 67 | t->size = size; 68 | t->name = name; 69 | t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry)); 70 | if(!t->table) lh_abort("lh_table_new: calloc failed\n"); 71 | t->free_fn = free_fn; 72 | t->hash_fn = hash_fn; 73 | t->equal_fn = equal_fn; 74 | for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY; 75 | return t; 76 | } 77 | 78 | struct lh_table* lh_kchar_table_new(int size, const char *name, 79 | lh_entry_free_fn *free_fn) 80 | { 81 | return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal); 82 | } 83 | 84 | struct lh_table* lh_kptr_table_new(int size, const char *name, 85 | lh_entry_free_fn *free_fn) 86 | { 87 | return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal); 88 | } 89 | 90 | void lh_table_resize(struct lh_table *t, int new_size) 91 | { 92 | struct lh_table *new_t; 93 | struct lh_entry *ent; 94 | 95 | new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn); 96 | ent = t->head; 97 | while(ent) { 98 | lh_table_insert(new_t, ent->k, ent->v); 99 | ent = ent->next; 100 | } 101 | free(t->table); 102 | t->table = new_t->table; 103 | t->size = new_size; 104 | t->head = new_t->head; 105 | t->tail = new_t->tail; 106 | t->resizes++; 107 | free(new_t); 108 | } 109 | 110 | void lh_table_free(struct lh_table *t) 111 | { 112 | struct lh_entry *c; 113 | for(c = t->head; c != NULL; c = c->next) { 114 | if(t->free_fn) { 115 | t->free_fn(c); 116 | } 117 | } 118 | free(t->table); 119 | free(t); 120 | } 121 | 122 | 123 | int lh_table_insert(struct lh_table *t, void *k, const void *v) 124 | { 125 | unsigned long h, n; 126 | 127 | t->inserts++; 128 | if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2); 129 | 130 | h = t->hash_fn(k); 131 | n = h % t->size; 132 | 133 | while( 1 ) { 134 | if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break; 135 | t->collisions++; 136 | if(++n == t->size) n = 0; 137 | } 138 | 139 | t->table[n].k = k; 140 | t->table[n].v = v; 141 | t->count++; 142 | 143 | if(t->head == NULL) { 144 | t->head = t->tail = &t->table[n]; 145 | t->table[n].next = t->table[n].prev = NULL; 146 | } else { 147 | t->tail->next = &t->table[n]; 148 | t->table[n].prev = t->tail; 149 | t->table[n].next = NULL; 150 | t->tail = &t->table[n]; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | 157 | struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k) 158 | { 159 | unsigned long h = t->hash_fn(k); 160 | unsigned long n = h % t->size; 161 | 162 | t->lookups++; 163 | while( 1 ) { 164 | if(t->table[n].k == LH_EMPTY) return NULL; 165 | if(t->table[n].k != LH_FREED && 166 | t->equal_fn(t->table[n].k, k)) return &t->table[n]; 167 | if(++n == t->size) n = 0; 168 | } 169 | return NULL; 170 | } 171 | 172 | 173 | const void* lh_table_lookup(struct lh_table *t, const void *k) 174 | { 175 | struct lh_entry *e = lh_table_lookup_entry(t, k); 176 | if(e) return e->v; 177 | return NULL; 178 | } 179 | 180 | 181 | int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) 182 | { 183 | ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ 184 | 185 | /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ 186 | if(n < 0) { return -2; } 187 | 188 | if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1; 189 | t->count--; 190 | if(t->free_fn) t->free_fn(e); 191 | t->table[n].v = NULL; 192 | t->table[n].k = LH_FREED; 193 | if(t->tail == &t->table[n] && t->head == &t->table[n]) { 194 | t->head = t->tail = NULL; 195 | } else if (t->head == &t->table[n]) { 196 | t->head->next->prev = NULL; 197 | t->head = t->head->next; 198 | } else if (t->tail == &t->table[n]) { 199 | t->tail->prev->next = NULL; 200 | t->tail = t->tail->prev; 201 | } else { 202 | t->table[n].prev->next = t->table[n].next; 203 | t->table[n].next->prev = t->table[n].prev; 204 | } 205 | t->table[n].next = t->table[n].prev = NULL; 206 | return 0; 207 | } 208 | 209 | 210 | int lh_table_delete(struct lh_table *t, const void *k) 211 | { 212 | struct lh_entry *e = lh_table_lookup_entry(t, k); 213 | if(!e) return -1; 214 | return lh_table_delete_entry(t, e); 215 | } 216 | 217 | -------------------------------------------------------------------------------- /lib/json/linkhash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _linkhash_h_ 13 | #define _linkhash_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /** 20 | * golden prime used in hash functions 21 | */ 22 | #define LH_PRIME 0x9e370001UL 23 | 24 | /** 25 | * sentinel pointer value for empty slots 26 | */ 27 | #define LH_EMPTY (void*)-1 28 | 29 | /** 30 | * sentinel pointer value for freed slots 31 | */ 32 | #define LH_FREED (void*)-2 33 | 34 | struct lh_entry; 35 | 36 | /** 37 | * callback function prototypes 38 | */ 39 | typedef void (lh_entry_free_fn) (struct lh_entry *e); 40 | /** 41 | * callback function prototypes 42 | */ 43 | typedef unsigned long (lh_hash_fn) (const void *k); 44 | /** 45 | * callback function prototypes 46 | */ 47 | typedef int (lh_equal_fn) (const void *k1, const void *k2); 48 | 49 | /** 50 | * An entry in the hash table 51 | */ 52 | struct lh_entry { 53 | /** 54 | * The key. 55 | */ 56 | void *k; 57 | /** 58 | * The value. 59 | */ 60 | const void *v; 61 | /** 62 | * The next entry 63 | */ 64 | struct lh_entry *next; 65 | /** 66 | * The previous entry. 67 | */ 68 | struct lh_entry *prev; 69 | }; 70 | 71 | 72 | /** 73 | * The hash table structure. 74 | */ 75 | struct lh_table { 76 | /** 77 | * Size of our hash. 78 | */ 79 | int size; 80 | /** 81 | * Numbers of entries. 82 | */ 83 | int count; 84 | 85 | /** 86 | * Number of collisions. 87 | */ 88 | int collisions; 89 | 90 | /** 91 | * Number of resizes. 92 | */ 93 | int resizes; 94 | 95 | /** 96 | * Number of lookups. 97 | */ 98 | int lookups; 99 | 100 | /** 101 | * Number of inserts. 102 | */ 103 | int inserts; 104 | 105 | /** 106 | * Number of deletes. 107 | */ 108 | int deletes; 109 | 110 | /** 111 | * Name of the hash table. 112 | */ 113 | const char *name; 114 | 115 | /** 116 | * The first entry. 117 | */ 118 | struct lh_entry *head; 119 | 120 | /** 121 | * The last entry. 122 | */ 123 | struct lh_entry *tail; 124 | 125 | struct lh_entry *table; 126 | 127 | /** 128 | * A pointer onto the function responsible for freeing an entry. 129 | */ 130 | lh_entry_free_fn *free_fn; 131 | lh_hash_fn *hash_fn; 132 | lh_equal_fn *equal_fn; 133 | }; 134 | 135 | 136 | /** 137 | * Pre-defined hash and equality functions 138 | */ 139 | extern unsigned long lh_ptr_hash(const void *k); 140 | extern int lh_ptr_equal(const void *k1, const void *k2); 141 | 142 | extern unsigned long lh_char_hash(const void *k); 143 | extern int lh_char_equal(const void *k1, const void *k2); 144 | 145 | 146 | /** 147 | * Convenience list iterator. 148 | */ 149 | #define lh_foreach(table, entry) \ 150 | for(entry = table->head; entry; entry = entry->next) 151 | 152 | /** 153 | * lh_foreach_safe allows calling of deletion routine while iterating. 154 | */ 155 | #define lh_foreach_safe(table, entry, tmp) \ 156 | for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) 157 | 158 | 159 | 160 | /** 161 | * Create a new linkhash table. 162 | * @param size initial table size. The table is automatically resized 163 | * although this incurs a performance penalty. 164 | * @param name the table name. 165 | * @param free_fn callback function used to free memory for entries 166 | * when lh_table_free or lh_table_delete is called. 167 | * If NULL is provided, then memory for keys and values 168 | * must be freed by the caller. 169 | * @param hash_fn function used to hash keys. 2 standard ones are defined: 170 | * lh_ptr_hash and lh_char_hash for hashing pointer values 171 | * and C strings respectively. 172 | * @param equal_fn comparison function to compare keys. 2 standard ones defined: 173 | * lh_ptr_hash and lh_char_hash for comparing pointer values 174 | * and C strings respectively. 175 | * @return a pointer onto the linkhash table. 176 | */ 177 | extern struct lh_table* lh_table_new(int size, const char *name, 178 | lh_entry_free_fn *free_fn, 179 | lh_hash_fn *hash_fn, 180 | lh_equal_fn *equal_fn); 181 | 182 | /** 183 | * Convenience function to create a new linkhash 184 | * table with char keys. 185 | * @param size initial table size. 186 | * @param name table name. 187 | * @param free_fn callback function used to free memory for entries. 188 | * @return a pointer onto the linkhash table. 189 | */ 190 | extern struct lh_table* lh_kchar_table_new(int size, const char *name, 191 | lh_entry_free_fn *free_fn); 192 | 193 | 194 | /** 195 | * Convenience function to create a new linkhash 196 | * table with ptr keys. 197 | * @param size initial table size. 198 | * @param name table name. 199 | * @param free_fn callback function used to free memory for entries. 200 | * @return a pointer onto the linkhash table. 201 | */ 202 | extern struct lh_table* lh_kptr_table_new(int size, const char *name, 203 | lh_entry_free_fn *free_fn); 204 | 205 | 206 | /** 207 | * Free a linkhash table. 208 | * If a callback free function is provided then it is called for all 209 | * entries in the table. 210 | * @param t table to free. 211 | */ 212 | extern void lh_table_free(struct lh_table *t); 213 | 214 | 215 | /** 216 | * Insert a record into the table. 217 | * @param t the table to insert into. 218 | * @param k a pointer to the key to insert. 219 | * @param v a pointer to the value to insert. 220 | */ 221 | extern int lh_table_insert(struct lh_table *t, void *k, const void *v); 222 | 223 | 224 | /** 225 | * Lookup a record into the table. 226 | * @param t the table to lookup 227 | * @param k a pointer to the key to lookup 228 | * @return a pointer to the record structure of the value or NULL if it does not exist. 229 | */ 230 | extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); 231 | 232 | /** 233 | * Lookup a record into the table 234 | * @param t the table to lookup 235 | * @param k a pointer to the key to lookup 236 | * @return a pointer to the found value or NULL if it does not exist. 237 | */ 238 | extern const void* lh_table_lookup(struct lh_table *t, const void *k); 239 | 240 | 241 | /** 242 | * Delete a record from the table. 243 | * If a callback free function is provided then it is called for the 244 | * for the item being deleted. 245 | * @param t the table to delete from. 246 | * @param e a pointer to the entry to delete. 247 | * @return 0 if the item was deleted. 248 | * @return -1 if it was not found. 249 | */ 250 | extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); 251 | 252 | 253 | /** 254 | * Delete a record from the table. 255 | * If a callback free function is provided then it is called for the 256 | * for the item being deleted. 257 | * @param t the table to delete from. 258 | * @param k a pointer to the key to delete. 259 | * @return 0 if the item was deleted. 260 | * @return -1 if it was not found. 261 | */ 262 | extern int lh_table_delete(struct lh_table *t, const void *k); 263 | 264 | 265 | void lh_abort(const char *msg, ...); 266 | void lh_table_resize(struct lh_table *t, int new_size); 267 | 268 | #ifdef __cplusplus 269 | } 270 | #endif 271 | 272 | #endif 273 | -------------------------------------------------------------------------------- /lib/json/printbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * 11 | * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. 12 | * The copyrights to the contents of this file are licensed under the MIT License 13 | * (http://www.opensource.org/licenses/mit-license.php) 14 | */ 15 | 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #if HAVE_STDARG_H 23 | # include 24 | #else /* !HAVE_STDARG_H */ 25 | # error Not enough var arg support! 26 | #endif /* HAVE_STDARG_H */ 27 | 28 | #include "bits.h" 29 | #include "debug.h" 30 | #include "printbuf.h" 31 | 32 | struct printbuf* printbuf_new(void) 33 | { 34 | struct printbuf *p; 35 | 36 | p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); 37 | if(!p) return NULL; 38 | p->size = 32; 39 | p->bpos = 0; 40 | if(!(p->buf = (char*)malloc(p->size))) { 41 | free(p); 42 | return NULL; 43 | } 44 | return p; 45 | } 46 | 47 | 48 | int printbuf_memappend(struct printbuf *p, const char *buf, int size) 49 | { 50 | char *t; 51 | if(p->size - p->bpos <= size) { 52 | int new_size = json_max(p->size * 2, p->bpos + size + 8); 53 | #ifdef PRINTBUF_DEBUG 54 | MC_DEBUG("printbuf_memappend: realloc " 55 | "bpos=%d wrsize=%d old_size=%d new_size=%d\n", 56 | p->bpos, size, p->size, new_size); 57 | #endif /* PRINTBUF_DEBUG */ 58 | if(!(t = (char*)realloc(p->buf, new_size))) return -1; 59 | p->size = new_size; 60 | p->buf = t; 61 | } 62 | memcpy(p->buf + p->bpos, buf, size); 63 | p->bpos += size; 64 | p->buf[p->bpos]= '\0'; 65 | return size; 66 | } 67 | 68 | #if !HAVE_VSNPRINTF && defined(WIN32) 69 | # define vsnprintf _vsnprintf 70 | #elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */ 71 | # error Need vsnprintf! 72 | #endif /* !HAVE_VSNPRINTF && defined(WIN32) */ 73 | 74 | #if !HAVE_VASPRINTF 75 | /* CAW: compliant version of vasprintf */ 76 | static int vasprintf(char **buf, const char *fmt, va_list ap) 77 | { 78 | #ifndef WIN32 79 | static char _T_emptybuffer = '\0'; 80 | #endif /* !defined(WIN32) */ 81 | int chars; 82 | char *b; 83 | 84 | if(!buf) { return -1; } 85 | 86 | #ifdef WIN32 87 | chars = _vscprintf(fmt, ap)+1; 88 | #else /* !defined(WIN32) */ 89 | /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite 90 | our buffer like on some 64bit sun systems.... but hey, its time to move on */ 91 | chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; 92 | if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ 93 | #endif /* defined(WIN32) */ 94 | 95 | b = (char*)malloc(sizeof(char)*chars); 96 | if(!b) { return -1; } 97 | 98 | if((chars = vsprintf(b, fmt, ap)) < 0) 99 | { 100 | free(b); 101 | } else { 102 | *buf = b; 103 | } 104 | 105 | return chars; 106 | } 107 | #endif /* !HAVE_VASPRINTF */ 108 | 109 | int sprintbuf(struct printbuf *p, const char *msg, ...) 110 | { 111 | va_list ap; 112 | char *t; 113 | int size; 114 | char buf[128]; 115 | 116 | /* user stack buffer first */ 117 | va_start(ap, msg); 118 | size = vsnprintf(buf, 128, msg, ap); 119 | va_end(ap); 120 | /* if string is greater than stack buffer, then use dynamic string 121 | with vasprintf. Note: some implementation of vsnprintf return -1 122 | if output is truncated whereas some return the number of bytes that 123 | would have been written - this code handles both cases. */ 124 | if(size == -1 || size > 127) { 125 | va_start(ap, msg); 126 | if((size = vasprintf(&t, msg, ap)) == -1) { va_end(ap); return -1; } 127 | va_end(ap); 128 | printbuf_memappend(p, t, size); 129 | free(t); 130 | return size; 131 | } else { 132 | printbuf_memappend(p, buf, size); 133 | return size; 134 | } 135 | } 136 | 137 | void printbuf_reset(struct printbuf *p) 138 | { 139 | p->buf[0] = '\0'; 140 | p->bpos = 0; 141 | } 142 | 143 | void printbuf_free(struct printbuf *p) 144 | { 145 | if(p) { 146 | free(p->buf); 147 | free(p); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /lib/json/printbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * 11 | * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. 12 | * The copyrights to the contents of this file are licensed under the MIT License 13 | * (http://www.opensource.org/licenses/mit-license.php) 14 | */ 15 | 16 | #ifndef _printbuf_h_ 17 | #define _printbuf_h_ 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #undef PRINTBUF_DEBUG 24 | 25 | struct printbuf { 26 | char *buf; 27 | int bpos; 28 | int size; 29 | }; 30 | 31 | extern struct printbuf* 32 | printbuf_new(void); 33 | 34 | /* As an optimization, printbuf_memappend is defined as a macro that 35 | * handles copying data if the buffer is large enough; otherwise it 36 | * invokes printbuf_memappend_real() which performs the heavy lifting 37 | * of realloc()ing the buffer and copying data. 38 | */ 39 | extern int 40 | printbuf_memappend(struct printbuf *p, const char *buf, int size); 41 | 42 | #define printbuf_memappend_fast(p, bufptr, bufsize) \ 43 | do { \ 44 | if ((p->size - p->bpos) > bufsize) { \ 45 | memcpy(p->buf + p->bpos, (bufptr), bufsize); \ 46 | p->bpos += bufsize; \ 47 | p->buf[p->bpos]= '\0'; \ 48 | } else { printbuf_memappend(p, (bufptr), bufsize); } \ 49 | } while (0) 50 | 51 | extern int 52 | sprintbuf(struct printbuf *p, const char *msg, ...); 53 | 54 | extern void 55 | printbuf_reset(struct printbuf *p); 56 | 57 | extern void 58 | printbuf_free(struct printbuf *p); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /lib/json/stamp-h1: -------------------------------------------------------------------------------- 1 | timestamp for config.h 2 | -------------------------------------------------------------------------------- /lib/json/test1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "json.h" 7 | 8 | int main(int argc, char **argv) 9 | { 10 | json_tokener *tok; 11 | json_object *my_string, *my_int, *my_object, *my_array; 12 | json_object *new_obj; 13 | int i; 14 | 15 | MC_SET_DEBUG(1); 16 | 17 | my_string = json_object_new_string("\t"); 18 | printf("my_string=%s\n", json_object_get_string(my_string)); 19 | printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); 20 | json_object_put(my_string); 21 | 22 | my_string = json_object_new_string("\\"); 23 | printf("my_string=%s\n", json_object_get_string(my_string)); 24 | printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); 25 | json_object_put(my_string); 26 | 27 | my_string = json_object_new_string("foo"); 28 | printf("my_string=%s\n", json_object_get_string(my_string)); 29 | printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); 30 | 31 | my_int = json_object_new_int(9); 32 | printf("my_int=%d\n", json_object_get_int(my_int)); 33 | printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int)); 34 | 35 | my_array = json_object_new_array(); 36 | json_object_array_add(my_array, json_object_new_int(1)); 37 | json_object_array_add(my_array, json_object_new_int(2)); 38 | json_object_array_add(my_array, json_object_new_int(3)); 39 | json_object_array_put_idx(my_array, 4, json_object_new_int(5)); 40 | printf("my_array=\n"); 41 | for(i=0; i < json_object_array_length(my_array); i++) { 42 | json_object *obj = json_object_array_get_idx(my_array, i); 43 | printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); 44 | } 45 | printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); 46 | 47 | my_object = json_object_new_object(); 48 | json_object_object_add(my_object, "abc", json_object_new_int(12)); 49 | json_object_object_add(my_object, "foo", json_object_new_string("bar")); 50 | json_object_object_add(my_object, "bool0", json_object_new_boolean(0)); 51 | json_object_object_add(my_object, "bool1", json_object_new_boolean(1)); 52 | json_object_object_add(my_object, "baz", json_object_new_string("bang")); 53 | json_object_object_add(my_object, "baz", json_object_new_string("fark")); 54 | json_object_object_del(my_object, "baz"); 55 | /*json_object_object_add(my_object, "arr", my_array);*/ 56 | printf("my_object=\n"); 57 | json_object_object_foreach(my_object, key, val) { 58 | printf("\t%s: %s\n", key, json_object_to_json_string(val)); 59 | } 60 | printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object)); 61 | 62 | new_obj = json_tokener_parse("\"\003\""); 63 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 64 | json_object_put(new_obj); 65 | 66 | new_obj = json_tokener_parse("/* hello */\"foo\""); 67 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 68 | json_object_put(new_obj); 69 | 70 | new_obj = json_tokener_parse("// hello\n\"foo\""); 71 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 72 | json_object_put(new_obj); 73 | 74 | new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\""); 75 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 76 | json_object_put(new_obj); 77 | 78 | new_obj = json_tokener_parse("null"); 79 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 80 | json_object_put(new_obj); 81 | 82 | new_obj = json_tokener_parse("True"); 83 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 84 | json_object_put(new_obj); 85 | 86 | new_obj = json_tokener_parse("12"); 87 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 88 | json_object_put(new_obj); 89 | 90 | new_obj = json_tokener_parse("12.3"); 91 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 92 | json_object_put(new_obj); 93 | 94 | new_obj = json_tokener_parse("[\"\\n\"]"); 95 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 96 | json_object_put(new_obj); 97 | 98 | new_obj = json_tokener_parse("[\"\\nabc\\n\"]"); 99 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 100 | json_object_put(new_obj); 101 | 102 | new_obj = json_tokener_parse("[null]"); 103 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 104 | json_object_put(new_obj); 105 | 106 | new_obj = json_tokener_parse("[]"); 107 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 108 | json_object_put(new_obj); 109 | 110 | new_obj = json_tokener_parse("[false]"); 111 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 112 | json_object_put(new_obj); 113 | 114 | new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]"); 115 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 116 | json_object_put(new_obj); 117 | 118 | new_obj = json_tokener_parse("{}"); 119 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 120 | json_object_put(new_obj); 121 | 122 | new_obj = json_tokener_parse("{ \"foo\": \"bar\" }"); 123 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 124 | json_object_put(new_obj); 125 | 126 | new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }"); 127 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 128 | json_object_put(new_obj); 129 | 130 | new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }"); 131 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 132 | json_object_put(new_obj); 133 | 134 | new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); 135 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 136 | json_object_put(new_obj); 137 | 138 | new_obj = json_tokener_parse("{ foo }"); 139 | if(is_error(new_obj)) printf("got error as expected\n"); 140 | 141 | new_obj = json_tokener_parse("foo"); 142 | if(is_error(new_obj)) printf("got error as expected\n"); 143 | 144 | new_obj = json_tokener_parse("{ \"foo"); 145 | if(is_error(new_obj)) printf("got error as expected\n"); 146 | 147 | /* test incremental parsing */ 148 | tok = json_tokener_new(); 149 | new_obj = json_tokener_parse_ex(tok, "{ \"foo", 6); 150 | if(is_error(new_obj)) printf("got error as expected\n"); 151 | new_obj = json_tokener_parse_ex(tok, "\": {\"bar", 8); 152 | if(is_error(new_obj)) printf("got error as expected\n"); 153 | new_obj = json_tokener_parse_ex(tok, "\":13}}", 6); 154 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 155 | json_object_put(new_obj); 156 | json_tokener_free(tok); 157 | 158 | json_object_put(my_string); 159 | json_object_put(my_int); 160 | json_object_put(my_object); 161 | //json_object_put(my_array); 162 | 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /lib/json/test2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "json.h" 7 | 8 | 9 | int main(int argc, char **argv) 10 | { 11 | json_object *new_obj; 12 | 13 | MC_SET_DEBUG(1); 14 | 15 | new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }"); 16 | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 17 | json_object_put(new_obj); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /lib/json/test3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "json.h" 5 | 6 | int 7 | main() 8 | { 9 | struct json_object *jobj; 10 | char *input = (char*)malloc(1024); 11 | 12 | while (fgets(input, 1024, stdin) != NULL) { 13 | jobj = json_tokener_parse(input); 14 | if (is_error(jobj)) { 15 | printf("error parsing json: %s\n", 16 | json_tokener_errors[-(unsigned long)jobj]); 17 | } else { 18 | printf("%s\n", json_object_to_json_string(jobj)); 19 | json_object_put(jobj); 20 | } 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/args_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | args_parser.c 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include "memqueue_impl.h" 26 | #include "args_parser.h" 27 | 28 | void 29 | args_memqueue_poll_populate(poll_args_t *user_args, h_hash_t *args) 30 | { 31 | 32 | char *total_queues_str = http_get_querystring("total_queues"); 33 | int i = 0; 34 | int j = 0; 35 | int total_queues = 0; 36 | char *fieldvalue = NULL; 37 | char *fieldname = NULL; 38 | char *fields[] = {"q_id", "rev", "latest", "consumer_id", 39 | "include_consumers", "timeout"}; 40 | 41 | memset(user_args, 0, sizeof (poll_args_t)); 42 | 43 | if (total_queues_str && args == NULL) 44 | total_queues = atoi(total_queues_str); 45 | else if (args != NULL) 46 | total_queues = 1; 47 | else 48 | total_queues = 0; 49 | 50 | for (i = 0; i < total_queues; i++) { 51 | for (j = 0; j < sizeof(fields) / sizeof (fields[0]); j++) { 52 | if (args == NULL) 53 | asprintf(&fieldname, "%s-%d", fields[j], i); 54 | else 55 | asprintf(&fieldname, "%s", fields[j]); 56 | 57 | if (args != NULL && j == 0) 58 | fieldvalue = h_get(args, fields[i]); 59 | else 60 | fieldvalue = http_get_querystring(fieldname); 61 | 62 | if (fieldvalue == NULL) { 63 | free(fieldname); 64 | continue; 65 | } 66 | 67 | switch(j) { 68 | case 0: 69 | user_args->queue_args[i].q_id = fieldvalue; 70 | break; 71 | case 1: 72 | user_args->queue_args[i].rev = atoi(fieldvalue); 73 | break; 74 | case 2: 75 | user_args->queue_args[i].latest = atoi(fieldvalue); 76 | break; 77 | case 3: 78 | user_args->queue_args[i].consumer_id = fieldvalue; 79 | break; 80 | case 4: 81 | user_args->queue_args[i].include_consumers = \ 82 | atoi(fieldvalue); 83 | break; 84 | } 85 | free(fieldname); 86 | } 87 | } 88 | 89 | user_args->total = total_queues; 90 | fieldvalue = http_get_querystring("timeout"); 91 | if (fieldvalue) 92 | user_args->timeout = atoi(fieldvalue); 93 | else 94 | user_args->timeout = -1; 95 | 96 | return; 97 | } 98 | 99 | void 100 | args_memqueue_create_populate(memqueue_create_args_t *user_args, h_hash_t *args) 101 | { 102 | 103 | int j = 0; 104 | char *fieldvalue = NULL; 105 | char *fieldname = NULL; 106 | char *fields[] = {"q_id", "max_size", 107 | "consumer_expiry", "expiry", "drop_from_head"}; 108 | 109 | memset(user_args, 0, sizeof (memqueue_create_args_t)); 110 | for (j = 0; j < sizeof(fields) / sizeof (fields[0]); j++) { 111 | fieldname = fields[j]; 112 | 113 | if (args != NULL && j == 0) 114 | fieldvalue = h_get(args, fields[j]); 115 | else 116 | fieldvalue = http_get_querystring(fieldname); 117 | 118 | if (fieldvalue == NULL) 119 | continue; 120 | 121 | switch(j) { 122 | case 0: 123 | user_args->q_id = fieldvalue; 124 | break; 125 | case 1: 126 | user_args->max_size = atoi(fieldvalue); 127 | break; 128 | case 2: 129 | user_args->consumer_expiry = atoi(fieldvalue); 130 | break; 131 | case 3: 132 | user_args->expiry = atoi(fieldvalue); 133 | break; 134 | case 4: 135 | user_args->drop_from_head = atoi(fieldvalue); 136 | break; 137 | } 138 | } 139 | 140 | return; 141 | } 142 | -------------------------------------------------------------------------------- /src/args_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | args_parser.h 20 | */ 21 | 22 | #ifndef _ARGS_PARSER_H_ 23 | #define _ARGS_PARSER_H_ 24 | 25 | typedef struct poll_args poll_args_t; 26 | typedef struct memqueue_create_args memqueue_create_args_t; 27 | struct poll_args; 28 | struct memqueue_create_args; 29 | 30 | struct poll_args { 31 | struct { 32 | int rev; 33 | int latest; 34 | char *consumer_id; 35 | char *q_id; 36 | int include_consumers; 37 | } queue_args[32]; 38 | int timeout; 39 | int total; 40 | }; 41 | 42 | struct memqueue_create_args { 43 | uint32_t expiry; 44 | int max_size; 45 | uint32_t consumer_expiry; 46 | int drop_from_head; 47 | char *q_id; 48 | }; 49 | 50 | void args_memqueue_poll_populate(poll_args_t *user_args, h_hash_t *args); 51 | void args_memqueue_create_populate(memqueue_create_args_t *user_args, 52 | h_hash_t *args); 53 | #endif 54 | -------------------------------------------------------------------------------- /src/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | hash.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include "hash.h" 28 | 29 | h_hash_t * 30 | h_init(int size) 31 | { 32 | h_hash_t *h = NULL; 33 | int i = 0; 34 | 35 | if ((h = calloc(1, sizeof(h_hash_t))) == NULL) 36 | return NULL; 37 | if ((h->buckets = calloc(1, size * sizeof(h_bucket_t))) == NULL) 38 | return NULL; 39 | 40 | h->size = size; 41 | h->order_next = NULL; 42 | 43 | for (i = 0; i < size; i++) 44 | LIST_INIT(&h->buckets[i].head); 45 | TAILQ_INIT(&h->order_head); 46 | 47 | return h; 48 | } 49 | 50 | int 51 | h_remove(h_hash_t *h, char *key) 52 | { 53 | int hash = 0; 54 | h_item_t *item = NULL, *item_tmp = NULL; 55 | 56 | hash = h_hash_func(key, strlen(key)) % h->size; 57 | LIST_FOREACH_SAFE(item, &h->buckets[hash].head, items, item_tmp) { 58 | if (strcmp(key, item->key) == 0) { 59 | LIST_REMOVE(item, items); 60 | TAILQ_REMOVE(&h->order_head, item, ordered_items); 61 | free(item); 62 | return 0; 63 | } 64 | } 65 | 66 | return -1; 67 | } 68 | 69 | int 70 | h_insert(h_hash_t *h, char *key, void *value) 71 | { 72 | h_item_t *item = NULL; 73 | h_item_t *curr_item = NULL; 74 | int hash = 0; 75 | 76 | hash = h_hash_func(key, strlen(key)) % h->size; 77 | 78 | LIST_FOREACH(curr_item, &h->buckets[hash].head, items) { 79 | if (strcmp(key, curr_item->key) == 0) 80 | return -1; 81 | } 82 | 83 | if ((item = calloc(1, sizeof(h_item_t))) == NULL) 84 | return -1; 85 | 86 | item->key = strdup(key); 87 | item->value = value; 88 | 89 | LIST_INSERT_HEAD(&h->buckets[hash].head, item, items); 90 | TAILQ_INSERT_TAIL(&h->order_head, item, ordered_items); 91 | 92 | return 0; 93 | } 94 | 95 | void 96 | h_init_traverse(h_hash_t *h) 97 | { 98 | h->order_next = NULL; 99 | } 100 | 101 | void * 102 | h_get(h_hash_t *h, char *key) 103 | { 104 | int hash = 0; 105 | h_item_t *item = NULL; 106 | 107 | hash = h_hash_func(key, strlen(key)) % h->size; 108 | LIST_FOREACH(item, &h->buckets[hash].head, items) { 109 | if (strcmp(key, item->key) == 0) 110 | return item->value; 111 | } 112 | 113 | return NULL; 114 | } 115 | 116 | h_item_t * 117 | h_next(h_hash_t *h) 118 | { 119 | if (h->order_next == NULL) 120 | h->order_next = TAILQ_FIRST(&h->order_head); 121 | else 122 | h->order_next = TAILQ_NEXT(h->order_next, ordered_items); 123 | 124 | /*if (h->order_next) 125 | printf("order_next is %p: %s %s\n", h->order_next, 126 | h->order_next->key, h->order_next->value);*/ 127 | return h->order_next; 128 | } 129 | 130 | void 131 | h_free(h_hash_t *h) 132 | { 133 | h_item_t *item = NULL; 134 | h_init_traverse(h); 135 | while (!TAILQ_EMPTY(&h->order_head)) { 136 | item = TAILQ_FIRST(&h->order_head); 137 | TAILQ_REMOVE(&h->order_head, item, ordered_items); 138 | free(item->key); 139 | free(item); 140 | } 141 | 142 | free(h->buckets); 143 | free(h); 144 | } 145 | 146 | uint32_t h_hash_func(const char *key, uint32_t len) 147 | { 148 | int i, hash = 0; 149 | 150 | for (i = 0; i < len; i++) 151 | hash += key[i]; 152 | 153 | return hash; 154 | } 155 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | hash.h 20 | */ 21 | #ifndef _HASHLIB_H_ 22 | #define _HASHLIB_H_ 23 | 24 | /* hash 25 | * ---------------------- 26 | * | entry | ----> item 27 | * ---------------------- 28 | * | entry | ----> item 29 | * ---------------------- 30 | * | entry | ----> item 31 | * ---------------------- 32 | */ 33 | #include 34 | #include 35 | 36 | uint32_t h_hash_func(const char *key, uint32_t len); 37 | 38 | struct h_item { 39 | char *key; 40 | char *value; 41 | int order; 42 | LIST_ENTRY(h_item) items; 43 | TAILQ_ENTRY(h_item) ordered_items; 44 | }; 45 | typedef struct h_item_t_l h_item_t_l; 46 | LIST_HEAD(h_item_t_l, h_item); 47 | TAILQ_HEAD(h_item_t_q, h_item); 48 | 49 | struct h_bucket { 50 | struct h_item_t_l head; 51 | }; 52 | 53 | typedef struct h_hash h_hash_t; 54 | typedef struct h_bucket h_bucket_t; 55 | typedef struct h_item h_item_t; 56 | 57 | struct h_hash { 58 | h_bucket_t *buckets; 59 | struct h_item_t_q order_head; 60 | int size; 61 | h_item_t *order_next; 62 | }; 63 | 64 | h_hash_t *h_init(int size); 65 | int h_remove(h_hash_t *h, char *key); 66 | int h_insert(h_hash_t *h, char *key, void *value); 67 | void h_init_traverse(h_hash_t *h); 68 | h_item_t *h_next(h_hash_t *h); 69 | void h_free(h_hash_t *h); 70 | void *h_get(h_hash_t *h, char *key); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/hash_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hash.h" 3 | 4 | 5 | int main () 6 | { 7 | h_hash_t *h; 8 | h_item_t *e; 9 | 10 | h = h_init(128); 11 | /* 12 | h_insert(h, "first_name", "Hasan"); 13 | printf("first name is: %s\n", h_get(h, "first_name")); 14 | h_remove(h, "first_name"); 15 | printf("first name is: %s\n", h_get(h, "first_name")); 16 | h_remove(h, "first_name"); 17 | printf("first name is: %s\n", h_get(h, "first_name")); 18 | 19 | */ 20 | h_insert(h, "first_name", "Hasan"); 21 | h_insert(h, "last_name", "Alayli"); 22 | h_insert(h, "age", "27"); 23 | h_insert(h, "location", "san francisco"); 24 | while ((e = h_next(h)) != NULL){ 25 | printf("entry is: %s: %s\n", e->key, e->value); 26 | } 27 | 28 | h_free(h); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /src/http.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http.h 20 | */ 21 | #ifndef _HTTP_H_ 22 | #define _HTTP_H_ 23 | 24 | #include "http_impl.h" 25 | 26 | int http_respond(int http_code, char *body, uint64_t body_len); 27 | void http_set_respcode(int); 28 | void *lsn_run(void *lsn); 29 | int lsn_init(lsn_t *lsn, route_handler_cb_t cb); 30 | void http_add_header(http_cli_t *cli, char *name, char *value); 31 | char *http_get_method_str(void); 32 | char *http_get_querystring(char *str); 33 | uint64_t http_get_body_len(void); 34 | char *http_get_body(void); 35 | char *http_get_path(void); 36 | int http_sendfile(int http_code, int fd); 37 | #endif 38 | -------------------------------------------------------------------------------- /src/http_bd.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_bd.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "sock_easy.h" 32 | 33 | struct cmd_opt { 34 | char *recvd; 35 | int len; 36 | int fd; 37 | }; 38 | typedef struct cmd_opt cmd_opt_t; 39 | 40 | #define NELEMENTS(x) (sizeof (x) / sizeof x[0]) 41 | 42 | void cmd_exit(struct cmd_opt *cmd); 43 | void cmd_help(struct cmd_opt *cmd); 44 | void cmd_man(struct cmd_opt *cmd); 45 | void cmd_ls(struct cmd_opt *cmd); 46 | void cmd_log(struct cmd_opt *cmd); 47 | 48 | int bd_cmd_add(char *cmd, char *arg, char *desc, void (*f)(cmd_opt_t *)); 49 | 50 | struct _cmd{ 51 | char cmd[256]; 52 | void (*func)(cmd_opt_t *); 53 | char desc[256]; 54 | char arg[256]; 55 | char *help; 56 | } cmds[256] = { 57 | /* help */ 58 | {"help", cmd_help, 59 | "print backdoor commands.", {0}, NULL}, 60 | /* man */ 61 | {"man", cmd_man, 62 | "print command description.", {0}, NULL}, 63 | /* exit */ 64 | {"exit", cmd_exit, 65 | "exit backdoor.", {0}, NULL}, 66 | /* quit */ 67 | {"quit", cmd_exit, 68 | "alias for exit.", {0}, NULL}, 69 | /* ls */ 70 | {"ls", cmd_ls, 71 | "list proxy and thread objects. `man ls` for more.", {0}, NULL}, 72 | /* log */ 73 | {"log", cmd_log, 74 | "show/set proxy log levels.", {0}, NULL}, 75 | {{0, 0, 0, 0, 0}} 76 | }; 77 | 78 | int 79 | is_whitespace(char *s) 80 | { 81 | while(*s) { 82 | if(!isspace(*s)) 83 | return 0; 84 | s++; 85 | } 86 | return 1; 87 | } 88 | 89 | int 90 | bd_cmd_add(char *cmd, char *arg, char *desc, void (*f)(cmd_opt_t *)) 91 | { 92 | int i; 93 | 94 | if (strlen(cmd) > 255 || strlen(arg) > 255 || strlen(desc) > 255) 95 | return -1; 96 | 97 | for (i = 0; i < NELEMENTS(cmds) && cmds[i].func; i++); 98 | 99 | if ((i + 1) == 256) 100 | return -1; 101 | 102 | strcpy(cmds[i].cmd, cmd); 103 | strcpy(cmds[i].arg, arg); 104 | strcpy(cmds[i].desc, desc); 105 | cmds[i].func = f; 106 | 107 | cmds[i + 1].func = NULL; 108 | 109 | return 0; 110 | } 111 | 112 | void 113 | get_cmd(struct _cmd *cmd, char *buff, int len) 114 | { 115 | int i, arg_len = 0, cmd_len = 0; 116 | char *line_end, *arg = NULL; 117 | 118 | cmd->func = NULL; 119 | bzero(cmd->cmd, sizeof(cmd->cmd)); 120 | bzero(cmd->arg, sizeof(cmd->arg)); 121 | line_end = strchr(buff, '\n'); 122 | if (!line_end) 123 | return; 124 | 125 | buff[len] = '\0'; 126 | if ((arg = strchr(buff, ' ')) != NULL) { 127 | cmd_len = arg - buff; 128 | while (isspace(*arg) && (++arg < line_end)); 129 | arg_len = line_end - arg; 130 | } else { 131 | cmd_len = line_end - buff - 1; 132 | } 133 | 134 | for(i = 0; i < NELEMENTS(cmds); i++) { 135 | if (strncmp(cmds[i].cmd, buff, cmd_len) == 0) { 136 | cmd->func = cmds[i].func; 137 | strncpy(cmd->cmd, cmds[i].cmd, 256); 138 | if (strncmp(cmds[i].arg, arg, arg_len) == 0) 139 | strncpy(cmd->arg, arg, arg_len); 140 | break; 141 | } 142 | } 143 | } 144 | 145 | void 146 | bd_lt_cli(int fd) 147 | { 148 | char buff[1024] = {0}; 149 | int ret; 150 | struct _cmd cmd; 151 | struct cmd_opt cmd_options; 152 | char *err = "Unknown Command\n"; 153 | 154 | DEFINE_LTHREAD; 155 | 156 | sprintf(buff, 157 | "Copyright (c) 2011 express backdoor\n\nlthread 1.0\n" 158 | "Play Nice.\n"); 159 | 160 | lthread_send(fd, buff, strlen(buff), 0); 161 | 162 | while (1) { 163 | bzero(buff, sizeof buff); 164 | ret = lthread_send(fd, "%", strlen("%"), 0); 165 | if (ret <= 0) 166 | break; 167 | ret = lthread_recv(fd, buff, 1024, 0, 0); 168 | if (ret <= 0) 169 | break; 170 | 171 | if(is_whitespace(buff)) 172 | continue; 173 | 174 | get_cmd(&cmd, buff, ret); 175 | if (cmd.func == NULL) { 176 | lthread_send(fd, err, strlen(err), 0); 177 | continue; 178 | } 179 | 180 | cmd_options.fd = fd; 181 | cmd_options.recvd = buff; 182 | cmd_options.len = ret; 183 | (*cmd.func)(&cmd_options); 184 | } 185 | 186 | close(fd); 187 | } 188 | 189 | void 190 | bd_lt_listener(int args) 191 | { 192 | lthread_t *lt_new; 193 | socklen_t addrlen; 194 | int s_fd, c_fd; 195 | struct sockaddr_in cin; 196 | 197 | DEFINE_LTHREAD; 198 | s_fd = e_listener("0.0.0.0", 5557); 199 | if (s_fd == -1) { 200 | perror("Cannot listen on socket"); 201 | return; 202 | } 203 | 204 | while (1) { 205 | c_fd = lthread_accept(s_fd, (struct sockaddr *)&cin, &addrlen); 206 | 207 | if (!c_fd) { 208 | break; 209 | } 210 | 211 | lthread_create(<_new, (void *)bd_lt_cli, (void *)(long)c_fd); 212 | } 213 | } 214 | 215 | void 216 | cmd_exit(struct cmd_opt *cmd) 217 | { 218 | close(cmd->fd); 219 | } 220 | 221 | void 222 | cmd_man(cmd_opt_t *cmd) 223 | { 224 | lthread_send(cmd->fd, "man", 3, 0); 225 | 226 | return; 227 | } 228 | 229 | void 230 | cmd_ls(cmd_opt_t *cmd) 231 | { 232 | /*char *tmp = lthread_summary(); 233 | lthread_send(cmd->fd, tmp, strlen(tmp), 0); 234 | free(tmp); */ 235 | 236 | return; 237 | } 238 | 239 | void 240 | cmd_log(cmd_opt_t *cmd) 241 | { 242 | lthread_send(cmd->fd, "log", 3, 0); 243 | 244 | return; 245 | } 246 | 247 | void 248 | cmd_help(struct cmd_opt *cmd) 249 | { 250 | int i, len = 1024; 251 | char resp[1024]; 252 | 253 | snprintf(resp, len, "lthread backdoor commands\n"); 254 | snprintf(&resp[strlen(resp)], len - strlen(resp), 255 | " %-8s %s\n", "cmd", "desc"); 256 | for(i = 0; i < NELEMENTS(cmds) && cmds[i].func; i++) { 257 | snprintf(&resp[strlen(resp)], len - strlen(resp), 258 | " %-8s", cmds[i].cmd); 259 | snprintf(&resp[strlen(resp)], len - strlen(resp), 260 | " %s\n", cmds[i].desc); 261 | if (lthread_send(cmd->fd, resp, strlen(resp), 0) == -1) 262 | return; 263 | bzero(resp, sizeof resp); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/http_bd.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_bd.h 20 | */ 21 | void bd_init(void); 22 | void bd_lt_listener(lthread_t *lt, int args); 23 | -------------------------------------------------------------------------------- /src/http_conn.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_conn.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "http_impl.h" 30 | 31 | int 32 | http_send(http_cli_t *cli, char *buf, uint64_t len) 33 | { 34 | return lthread_send(cli->conn.fd, buf, len, 0); 35 | } 36 | 37 | int 38 | http_recv(http_cli_t *cli, char *buf, uint64_t len) 39 | { 40 | return lthread_recv(cli->conn.fd, buf, len, 0, 0); 41 | } 42 | -------------------------------------------------------------------------------- /src/http_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_impl.h 20 | */ 21 | #ifndef _HTTP_IMPL_H_ 22 | #define _HTTP_IMPL_H_ 23 | 24 | #include 25 | #include 26 | #include "http_str.h" 27 | #include "hash.h" 28 | 29 | #define TCP_BUF_SIZE (32*1024) 30 | #define HTTP_MAX_HDR_LEN (8192) 31 | #define HTTP_MAX_HDRS (64) 32 | #define HTTP_MAX_HOST_LEN (255) 33 | #define HTTP_MAX_REQ_LINE_LEN (4096) 34 | #define HTTP_DEFAULT_SERVER_PORT (80) 35 | #define NOMEM "Memory Error: " 36 | 37 | #define NELEMENTS(x) (sizeof (x) / sizeof x[0]) 38 | #define IS_SET(x, y) ((x) & (1<<(y))) 39 | #define SET_BIT(x, y) ((x) |= (1<<(y))) 40 | 41 | typedef enum { 42 | HTTP_GET = 1, 43 | HTTP_POST, 44 | HTTP_PUT, 45 | HTTP_HEAD, 46 | HTTP_DELETE, 47 | } http_method_t; 48 | 49 | typedef struct lsn lsn_t; 50 | typedef struct http_cli http_cli_t; 51 | typedef struct http_hdr http_hdr_t; 52 | typedef struct http_req http_req_t; 53 | typedef struct http_resp http_resp_t; 54 | typedef struct http_conn http_conn_t; 55 | 56 | typedef enum { 57 | HTTP_FAIL = -1, 58 | HTTP_ERR_UNKNOWN_HOST, /* no host in url or host hdr */ 59 | HTTP_ERR_NO_CNT_LEN, /* no content length */ 60 | HTTP_ERR_MAX_HDR_EXC, /* max hdr size exceeded */ 61 | HTTP_ERR_CLI_CLOSED, /* cli closed connection */ 62 | HTTP_ERR_INV_REQ_LINE, /* invalid request line */ 63 | HTTP_ERR_INV_METHOD, /* invalid method */ 64 | HTTP_ERR_INV_HOST, /* invalid host format */ 65 | HTTP_ERR_INV_PORT, /* port out of range */ 66 | HTTP_ERR_INV_PROTO, /* invalid protocol */ 67 | HTTP_ERR_TIMEOUT_EXC, /* read/write timeout exceeded */ 68 | HTTP_ERR_INV_HDR, /* hdr contains null or not complaint */ 69 | } http_req_err_t; 70 | 71 | struct http_hdr { 72 | char hdr[HTTP_MAX_HDR_LEN]; 73 | int hdr_start; 74 | int hdr_len; 75 | uint64_t cnt_len; /* content-length or chunk size */ 76 | unsigned chunked:1; 77 | unsigned nolen:1; 78 | unsigned keepalive:1; 79 | unsigned http11:1; 80 | unsigned expect100:1; 81 | h_hash_t *hdrs; 82 | }; 83 | 84 | /* 85 | * Request Structure 86 | */ 87 | struct http_req { 88 | char *host; 89 | http_method_t method; 90 | char *method_str; 91 | char *req_line; 92 | char *uri; 93 | unsigned short port; /* port if any (default 80) */ 94 | http_hdr_t hdr; 95 | char *body; 96 | uint64_t body_len; 97 | char *path; 98 | char *query_string; 99 | h_hash_t *query_string_args; 100 | }; 101 | 102 | /* 103 | * Response Structure 104 | */ 105 | 106 | typedef enum { 107 | HTTP_HDR_BEGIN, 108 | HTTP_HDR_SENT, 109 | HTTP_BODY_SENT 110 | } resp_state_t; 111 | 112 | struct http_resp { 113 | int respcode; 114 | char *respcode_int; 115 | char *respcode_str; 116 | h_hash_t *hdrs; 117 | char *body; 118 | uint64_t body_len; 119 | resp_state_t state; 120 | }; 121 | 122 | /* 123 | * Connection Structure 124 | */ 125 | struct http_conn { 126 | int fd; 127 | struct sockaddr_in peer_addr; 128 | }; 129 | 130 | /* 131 | * Client Structure 132 | */ 133 | struct http_cli { 134 | http_req_t req; 135 | http_resp_t resp; 136 | lsn_t *lsn; 137 | lthread_t *lt; 138 | http_conn_t conn; 139 | }; 140 | 141 | /* 142 | * listener Structure 143 | */ 144 | typedef int (*route_handler_cb_t)(void); 145 | struct lsn { 146 | unsigned short lsn_port; 147 | struct in_addr lsn_addr; 148 | uint64_t birth; 149 | route_handler_cb_t router_cb; 150 | }; 151 | 152 | /* 153 | * from http_conn.c 154 | */ 155 | int http_send(http_cli_t *cli, char *buf, uint64_t len); 156 | int http_recv(http_cli_t *cli, char *buf, uint64_t len); 157 | 158 | /* 159 | * from http_parser.c 160 | */ 161 | int http_parse_req_line(http_cli_t *cli); 162 | int http_parse_req_hdr(http_cli_t *cli); 163 | int http_parse_hdr(http_cli_t *cli); 164 | #endif 165 | -------------------------------------------------------------------------------- /src/http_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_parser.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "log.h" 27 | #include "http_impl.h" 28 | 29 | int 30 | http_parse_req_line(http_cli_t *c) 31 | { 32 | typedef enum {st_host = 0, 33 | st_uri, 34 | st_proto, 35 | st_port} st_state; 36 | int uri_start = 0; 37 | int port_start = 0; 38 | int host_start = 0; 39 | int proto_start = 0; 40 | char *hdr = c->req.hdr.hdr; 41 | int len = c->req.hdr.hdr_len; 42 | st_state state = st_host; 43 | int p = 0; 44 | c->req.port = HTTP_DEFAULT_SERVER_PORT; 45 | 46 | if (len < 7) 47 | return HTTP_ERR_INV_REQ_LINE; 48 | 49 | if (strncasecmp(hdr, "GET", 3) == 0) { 50 | c->req.method = HTTP_GET; 51 | c->req.method_str = "GET"; 52 | p += 3; 53 | } else if (strncasecmp(hdr, "PUT", 3) == 0) { 54 | c->req.method = HTTP_PUT; 55 | c->req.method_str = "PUT"; 56 | p += 3; 57 | } else if (strncasecmp(hdr, "DELETE", 6) == 0) { 58 | c->req.method = HTTP_DELETE; 59 | c->req.method_str = "DELETE"; 60 | p += 6; 61 | } else if (strncasecmp(hdr, "POST", 4) == 0) { 62 | c->req.method = HTTP_POST; 63 | c->req.method_str = "POST"; 64 | p += 4; 65 | } else if (strncasecmp(hdr, "HEAD", 4) == 0) { 66 | c->req.method = HTTP_HEAD; 67 | c->req.method_str = "HEAD"; 68 | p += 4; 69 | } else { 70 | return HTTP_ERR_INV_METHOD; 71 | } 72 | 73 | while (p < len && isspace(hdr[p])) 74 | p++; 75 | if (p == len) 76 | return HTTP_ERR_INV_REQ_LINE; 77 | 78 | state = st_uri; 79 | 80 | while (p < len) { 81 | switch (state) { 82 | case st_host: 83 | if (HTTP_IS_HOST_TERMINATOR((unsigned char)hdr[p])) { 84 | if (host_start == p) 85 | return HTTP_ERR_INV_HOST; 86 | if ((p - host_start) > HTTP_MAX_HOST_LEN) 87 | return HTTP_ERR_INV_HOST; 88 | if ((c->req.host = \ 89 | strndup(&hdr[host_start], p - host_start)) == NULL) { 90 | LOG_ERROR(NOMEM "not enough memory to copy host"); 91 | return HTTP_FAIL; 92 | } 93 | if (hdr[p] == ':') { 94 | state = st_port; 95 | p++; 96 | goto st_port; 97 | } else { 98 | state = st_uri; 99 | goto st_uri; 100 | } 101 | } 102 | 103 | if (!HTTP_IS_HOST_TOKEN(hdr[p])) 104 | return HTTP_ERR_INV_HOST; 105 | p++; 106 | break; 107 | case st_port: 108 | st_port: 109 | port_start = p; 110 | while (p < len && HTTP_IS_DIGIT(hdr[p])) 111 | p++; 112 | 113 | if (port_start == p) 114 | return HTTP_ERR_INV_PORT; 115 | c->req.port = http_strtol(&hdr[port_start], p - port_start, 10); 116 | if (c->req.port > 65534 || c->req.port < 1) 117 | return HTTP_ERR_INV_PORT; 118 | state = st_uri; 119 | goto st_uri; 120 | case st_uri: 121 | st_uri: 122 | uri_start = p; 123 | 124 | while (p < len && !isspace(hdr[p])) 125 | p++; 126 | 127 | if (p == len) 128 | return HTTP_ERR_INV_REQ_LINE; 129 | if ((c->req.uri = strndup(&hdr[uri_start], p - uri_start)) == NULL) 130 | abort(); 131 | while (p < len && isspace(hdr[p])) { 132 | p++; 133 | } 134 | state = st_proto; 135 | goto st_proto; 136 | case st_proto: 137 | st_proto: 138 | proto_start = p; 139 | 140 | while (p < len && !HTTP_IS_CR_OR_LF(hdr[p])) 141 | p++; 142 | 143 | if (p == len){ 144 | return HTTP_ERR_INV_REQ_LINE; 145 | } 146 | 147 | if ((p - proto_start) != 8) 148 | return HTTP_ERR_INV_PROTO; 149 | 150 | if (strncasecmp(&hdr[proto_start], "HTTP/1.1", 8) == 0) { 151 | c->req.hdr.http11 = 1; 152 | } else if ( 153 | strncasecmp(&hdr[proto_start], "HTTP/1.0", 8) == 0) { 154 | c->req.hdr.http11 = 0; 155 | } else { 156 | return HTTP_ERR_INV_PROTO; 157 | } 158 | 159 | while (p < len && hdr[p] == '\0') 160 | p++; 161 | 162 | c->req.hdr.hdr[p - 1] = '\0'; 163 | c->req.hdr.hdr_start = p; 164 | 165 | return 0; 166 | } 167 | } 168 | 169 | return HTTP_ERR_INV_REQ_LINE; 170 | } 171 | 172 | int 173 | http_parse_req_hdr(http_cli_t *c) 174 | { 175 | int ret = 0; 176 | char *tmp = NULL, *p = NULL; 177 | int i = 0; 178 | 179 | for (i = 0; i < c->req.hdr.hdr_len; i++) 180 | if (c->req.hdr.hdr[i] == '\0') 181 | return HTTP_ERR_INV_HDR; 182 | 183 | if ((ret = http_parse_req_line(c)) != 0) 184 | return ret; 185 | if ((ret = http_parse_hdr(c)) != 0) 186 | return ret; 187 | 188 | tmp = (char *)h_get(c->req.hdr.hdrs, "content-length"); 189 | if (tmp) 190 | c->req.hdr.cnt_len = strtol(tmp, NULL, 10); 191 | tmp = (char *)h_get(c->req.hdr.hdrs, "transfer-encoding"); 192 | if (tmp) 193 | c->req.hdr.chunked = 1; 194 | 195 | 196 | tmp = (char *)h_get(c->req.hdr.hdrs, "host"); 197 | if (tmp) { 198 | if ((p = strchr(tmp, ':')) != NULL) { 199 | if ((p - tmp) > HTTP_MAX_HOST_LEN) 200 | return HTTP_ERR_INV_HOST; 201 | if (c->req.host) 202 | free(c->req.host); 203 | if ((c->req.host = strndup(tmp, p - tmp)) == NULL) { 204 | LOG_ERROR(NOMEM "not enough memory to copy host"); 205 | return HTTP_FAIL; 206 | } 207 | c->req.port = strtol(p, NULL, 10); 208 | } else { 209 | if (c->req.host) 210 | free(c->req.host); 211 | if ((c->req.host = strndup(tmp, p - tmp)) == NULL) { 212 | LOG_ERROR(NOMEM "not enough memory to copy host"); 213 | return HTTP_FAIL; 214 | } 215 | } 216 | } 217 | 218 | 219 | 220 | return 0; 221 | } 222 | 223 | int 224 | http_parse_hdr(http_cli_t *cli) 225 | { 226 | int i = 0; 227 | char *p = NULL, *q = NULL; 228 | int start = cli->req.hdr.hdr_start; 229 | 230 | for (i = cli->req.hdr.hdr_start; i < cli->req.hdr.hdr_len; i++) { 231 | if (cli->req.hdr.hdr[i] == '\n') { 232 | /* check if hdr is continuing on new line */ 233 | if ((cli->req.hdr.hdr_len - i) && !isspace(cli->req.hdr.hdr[i + 1])) 234 | cli->req.hdr.hdr[i] = '\0'; 235 | else 236 | continue; 237 | 238 | /* terminate at \r if it exist */ 239 | if (i && cli->req.hdr.hdr[i - 1] == '\r') 240 | cli->req.hdr.hdr[i - 1] = '\0'; 241 | 242 | p = strchr(&cli->req.hdr.hdr[start], ':'); 243 | if (p == NULL) { 244 | start = i + 1; 245 | continue; 246 | } 247 | 248 | *p = '\0'; 249 | for (q = &cli->req.hdr.hdr[start]; *q; q++) 250 | *q = tolower(*q); 251 | p++; 252 | while (*p && !isspace(*p)) 253 | p++; 254 | h_insert(cli->req.hdr.hdrs, &cli->req.hdr.hdr[start], p + 1); 255 | start = i + 1; 256 | } 257 | } 258 | 259 | return 0; 260 | } 261 | -------------------------------------------------------------------------------- /src/http_str.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_str.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "http_str.h" 28 | 29 | const char is_host_terminator[256] = {[':'] = 1, ['/'] = 1, [' '] = 1}; 30 | 31 | const char is_cr_or_lf[256] = {[LF] = 1, [CR] = 1}; 32 | 33 | const char is_digit[256] = { 34 | ['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, 35 | ['4'] = 1, ['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1, 36 | }; 37 | 38 | const char is_sep[256] = {[' '] = 1, ['\t'] = 1}; 39 | 40 | const char is_host_token[256] = { 41 | ['0' ... '9'] = 1, 42 | ['A' ... 'Z'] = 1, 43 | ['a' ... 'z'] = 1, 44 | ['.'] = 1, 45 | ['-'] = 1, 46 | }; 47 | 48 | const char is_hex[256] = { 49 | ['x'] = 1, ['X'] = 1, ['0' ... '9'] = 1, 50 | ['a' ... 'f'] = 1, ['A' ... 'F'] = 1, 51 | }; 52 | 53 | const char is_al[256] = {['a' ... 'z'] = 1}; 54 | 55 | const char is_al_cap[256] = {['A' ... 'Z'] = 1}; 56 | 57 | const char is_space[256] = {[' ']=1}; 58 | 59 | const char upper[256] = { 60 | ['\t'] = '\t', 61 | ['\n'] = '\n', 62 | ['\r'] = '\r', 63 | [' '] = ' ', 64 | ['!'] = '!', 65 | ['"'] = '"', 66 | ['#'] = '#', 67 | ['$'] = '$', 68 | ['%'] = '%', 69 | ['&'] = '&', 70 | ['\''] = '\'', 71 | ['('] = '(', 72 | [')'] = ')', 73 | ['*'] = '*', 74 | ['+'] = '+', 75 | [','] = ',', 76 | ['-'] = '-', 77 | ['.'] = '.', 78 | ['/'] = '/', 79 | ['0'] = '0', 80 | ['1'] = '1', 81 | ['2'] = '2', 82 | ['3'] = '3', 83 | ['4'] = '4', 84 | ['5'] = '5', 85 | ['6'] = '6', 86 | ['7'] = '7', 87 | ['8'] = '8', 88 | ['9'] = '9', 89 | [':'] = ':', 90 | [';'] = ';', 91 | ['<'] = '<', 92 | ['='] = '=', 93 | ['>'] = '>', 94 | ['?'] = '?', 95 | ['@'] = '@', 96 | ['A'] = 'A', 97 | ['B'] = 'B', 98 | ['C'] = 'C', 99 | ['D'] = 'D', 100 | ['E'] = 'E', 101 | ['F'] = 'F', 102 | ['G'] = 'G', 103 | ['H'] = 'H', 104 | ['I'] = 'I', 105 | ['J'] = 'J', 106 | ['K'] = 'K', 107 | ['L'] = 'L', 108 | ['M'] = 'M', 109 | ['N'] = 'N', 110 | ['O'] = 'O', 111 | ['P'] = 'P', 112 | ['Q'] = 'Q', 113 | ['R'] = 'R', 114 | ['S'] = 'S', 115 | ['T'] = 'T', 116 | ['U'] = 'U', 117 | ['V'] = 'V', 118 | ['W'] = 'W', 119 | ['X'] = 'X', 120 | ['Y'] = 'Y', 121 | ['Z'] = 'Z', 122 | ['['] = '[', 123 | ['\\'] = '\\', 124 | [']'] = ']', 125 | ['^'] = '^', 126 | ['_'] = '_', 127 | ['`'] = '`', 128 | ['a'] = 'A', 129 | ['b'] = 'B', 130 | ['c'] = 'C', 131 | ['d'] = 'D', 132 | ['e'] = 'E', 133 | ['f'] = 'F', 134 | ['g'] = 'G', 135 | ['h'] = 'H', 136 | ['i'] = 'I', 137 | ['j'] = 'J', 138 | ['k'] = 'K', 139 | ['l'] = 'L', 140 | ['m'] = 'M', 141 | ['n'] = 'N', 142 | ['o'] = 'O', 143 | ['p'] = 'P', 144 | ['q'] = 'Q', 145 | ['r'] = 'R', 146 | ['s'] = 'S', 147 | ['t'] = 'T', 148 | ['u'] = 'U', 149 | ['v'] = 'V', 150 | ['w'] = 'W', 151 | ['x'] = 'X', 152 | ['y'] = 'Y', 153 | ['z'] = 'Z', 154 | ['{'] = '{', 155 | ['|'] = '|', 156 | ['}'] = '}', 157 | ['~'] = '~', 158 | }; 159 | 160 | #define to_upper(x) upper[(unsigned char)x] 161 | 162 | int 163 | http_strcasecmp(http_str_t *s1, http_str_t *s2) 164 | { 165 | int i; 166 | if (s1->len != s2->len) 167 | return -1; 168 | 169 | i = s1->len - 1; 170 | while (i) { 171 | if (s1->str[i] != s2->str[i] && (s1->str[i] - 32) != s2->str[i]) 172 | return -1; 173 | i--; 174 | } 175 | 176 | return 0; 177 | } 178 | 179 | char* 180 | http_strcasestr(char *s1, char *s2, int len, int len2) 181 | { 182 | int i = 0, j = 0; 183 | 184 | while (1) { 185 | /* find the first char that matches */ 186 | while(to_upper(s1[i]) != to_upper(s2[0]) && i++ <= len); 187 | 188 | /* pattern cannot fit in what's remaining */ 189 | if ((len - i) < len2) 190 | return NULL; 191 | 192 | j = 0; 193 | 194 | while (to_upper(s1[i + j]) == to_upper(s2[j]) && j < len2) 195 | j++; 196 | 197 | if (j == len2) { 198 | return &s1[i]; 199 | } 200 | i += j; 201 | } 202 | 203 | return NULL; 204 | } 205 | 206 | char* 207 | http_strcasechr(char *s1, char c2, int len) 208 | { 209 | int i = 0; 210 | 211 | while (i < len && s1[i] != c2) 212 | i++; 213 | 214 | if (i == len) 215 | return NULL; 216 | 217 | return &s1[i]; 218 | } 219 | 220 | long 221 | http_strtol(char *s1, int len, int base) 222 | { 223 | const char *s; 224 | long acc = 0; 225 | char c; 226 | long cutoff; 227 | int neg, any, cutlim; 228 | 229 | /* 230 | * Skip white space and pick up leading +/- sign if any. 231 | * If base is 0, allow 0x for hex and 0 for octal, else 232 | * assume decimal; if base is already 16, allow 0x. 233 | */ 234 | s = s1; 235 | //printf ("len is : %d, base is: %d\n", len, base); 236 | do { 237 | c = *s++; 238 | } while (HTTP_IS_SPACE(c) && &s1[len] > (s + 1)); 239 | 240 | if (c == '-') { 241 | neg = 1; 242 | c = *s++; 243 | } else { 244 | neg = 0; 245 | if (c == '+') 246 | c = *s++; 247 | } 248 | 249 | if ((base == 0 || base == 16) && HTTP_IS_HEX(*s) && c == '0') { 250 | if (&s1[len] >= (s + 2)) 251 | goto noconv; 252 | c = s[1]; 253 | s += 2; 254 | base = 16; 255 | } 256 | if (base == 0) 257 | base = c == '0' ? 8 : 10; 258 | acc = any = 0; 259 | if (base < 2 || base > 36) 260 | goto noconv; 261 | 262 | cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX 263 | : LONG_MAX; 264 | cutlim = cutoff % base; 265 | cutoff /= base; 266 | for ( ; &s1[len] >= s; c = *s++) { 267 | if (HTTP_IS_DIGIT(c)) 268 | c -= '0'; 269 | else if (HTTP_IS_AL_CAP(c)) 270 | c -= 'A' - 10; 271 | else if (HTTP_IS_AL(c)) 272 | c -= 'a' - 10; 273 | else 274 | break; 275 | if (c >= base) 276 | break; 277 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 278 | any = -1; 279 | else { 280 | any = 1; 281 | acc *= base; 282 | acc += c; 283 | } 284 | } 285 | if (any < 0) { 286 | acc = neg ? LONG_MIN : LONG_MAX; 287 | errno = ERANGE; 288 | } else if (!any) { 289 | noconv: 290 | errno = EINVAL; 291 | } else if (neg) 292 | acc = -acc; 293 | 294 | return (acc); 295 | } 296 | 297 | 298 | void 299 | http_print_exact(char *s, int len) 300 | { 301 | int i; 302 | 303 | for (i = 0; i < len; i++) 304 | if (s[i] == '\0') 305 | printf("\\0"); 306 | else if (s[i] == '\r') 307 | printf("\\r"); 308 | else if (s[i] == ' ' || s[i] == '\t') 309 | printf("."); 310 | else if (s[i] == '\n') { 311 | printf("\\n"); 312 | printf("\n"); 313 | } 314 | else 315 | printf("%c", s[i]); 316 | printf("END\n"); 317 | } 318 | 319 | unsigned 320 | hash_str(char *s, int hash_length) 321 | { 322 | unsigned hashval = 0; 323 | for (hashval = 0; *s != '\0'; s++) 324 | hashval = *s + 31 * hashval; 325 | return hashval % hash_length; 326 | } 327 | 328 | int http_strtol2(const char *s, int len) 329 | { 330 | int i = 0; 331 | int j, k; 332 | 333 | if (len > 0) { 334 | if (*s != '-') { 335 | /* positive number */ 336 | while (len-- > 0) { 337 | j = (*s++) - '0'; 338 | k = i * 10; 339 | if (j > 9) 340 | break; 341 | i = k + j; 342 | } 343 | } else { 344 | /* negative number */ 345 | s++; 346 | while (--len > 0) { 347 | j = (*s++) - '0'; 348 | k = i * 10; 349 | if (j > 9) 350 | break; 351 | i = k - j; 352 | } 353 | } 354 | } 355 | return i; 356 | } 357 | -------------------------------------------------------------------------------- /src/http_str.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | http_str.h 20 | */ 21 | #ifndef _HTTP_STR_H_ 22 | #define _HTTP_STR_H_ 23 | #include 24 | #include 25 | 26 | struct http_str { 27 | char *str; 28 | size_t len; 29 | }; 30 | 31 | typedef struct http_str http_str_t; 32 | 33 | 34 | #define LF '\n' 35 | #define CR '\r' 36 | #define CRLF "\r\n" 37 | #define LFLF "\n\n" 38 | 39 | extern const char is_host_token[256]; 40 | extern const char is_sep[256]; 41 | extern const char is_cr_or_lf[256]; 42 | extern const char is_digit[256]; 43 | extern const char is_host_terminator[256]; 44 | extern const char is_hex[256]; 45 | extern const char is_al[256]; 46 | extern const char is_al_cap[256]; 47 | extern const char is_space[256]; 48 | 49 | #define HTTP_IS_HOST_TERMINATOR(x) (is_host_terminator[((uint8_t)x)]) 50 | #define HTTP_IS_CR_OR_LF(x) (is_cr_or_lf[((uint8_t)x)]) 51 | #define HTTP_IS_DIGIT(x) (is_digit[((uint8_t)x)]) 52 | #define HTTP_IS_SEP(x) (is_sep[((uint8_t)x)]) 53 | #define HTTP_IS_HOST_TOKEN(x) (is_host_token[((uint8_t)x)]) 54 | #define HTTP_IS_HEX(x) (is_hex[((uint8_t)x)]) 55 | #define HTTP_IS_AL(x) (is_al[((uint8_t)x)]) 56 | #define HTTP_IS_AL_CAP(x) (is_al_cap[((uint8_t)x)]) 57 | #define HTTP_IS_SPACE(x) (is_space[((uint8_t)x)]) 58 | 59 | char *http_strcasestr(char *s1, char *s2, int len, int len2); 60 | char *http_strcasechr(char *s1, char s2, int len); 61 | int http_strcasecmp(http_str_t *s1, http_str_t *s2); 62 | long http_strtol(char *s1, int len, int base); 63 | int http_strtol2(const char *s, int len); 64 | void http_print_exact(char *s, int len); 65 | unsigned hash_str(char *s, int hash_len); 66 | 67 | #define http_strcmp2(s1, s2) \ 68 | (*(uint16_t *)(s1) == (*(uint16_t*)(s2))) 69 | 70 | #define http_strcmp3(s1, s2) \ 71 | ((*(uint32_t *)(s1) << 8) == (*(uint32_t *)(s2) << 8)) 72 | 73 | #define http_strcmp4(s1, s2) \ 74 | (*(uint32_t *)(s1) == (*(uint32_t*)(s2))) 75 | 76 | #define http_strcmp5(s1, s2) \ 77 | (http_strcmp4(s1, s2) && s1[4] == s2[4]) 78 | 79 | #define http_strcmp6(s1, s2) \ 80 | (http_strcmp4(s1, s2) && (http_strcmp2(s1 + 4, s2 + 4))) 81 | 82 | #define http_strcmp7(s1, s2) \ 83 | (http_strcmp6(s1, s2) && (s1)[6] == s2[6]) 84 | 85 | #define http_strcmp8(s1, s2) \ 86 | http_strcmp4(s1, s2) && http_strcmp4(s1 + 4, s2 + 4) 87 | 88 | #define http_strcmp9(s1, s2) \ 89 | (http_strcmp4(s1, s2) && http_strcmp4(s1 + 4, s2 + 4) && (s1)[8] == s2[8]) 90 | 91 | #define http_tolower(c) ((HTTP_IS_AL_CAP(c)) ? (c | 0x20) : c) 92 | #define http_toupper(c) ((HTTP_IS_AL(c)) ? (c & ~0x20) : c) 93 | 94 | 95 | #define http_strcasecmp2(s1, c0, c1) \ 96 | (http_toupper((s1)[0]) == c0 && http_toupper((s1)[1]) == c1) 97 | 98 | #define http_strcasecmp3(s1, c0, c1, c2) \ 99 | (http_strcasecmp2(s1, c0, c1) && http_toupper((s1)[2]) == c2) 100 | 101 | #define http_strcasecmp4(s1, c0, c1, c2, c3) \ 102 | (http_strcasecmp2(s1, c0, c1) && http_strcasecmp2(s1 + 2, c2, c3)) 103 | 104 | #define http_strcasecmp5(s1, c0, c1, c2, c3, c4) \ 105 | (http_strcasecmp2(s1, c0, c1) && http_strcasecmp2(s1 + 2, c2, c3) && \ 106 | http_toupper((s1)[4]) == http_toupper(c4)) 107 | 108 | #define http_strcasecmp6(s1, c0, c1, c2, c3, c4, c5) \ 109 | (http_strcasecmp4(s1, c0, c1, c2, c3) && \ 110 | http_strcasecmp2(s1 + 4, c4, c5)) 111 | 112 | #define http_strcasecmp7(s1, c0, c1, c2, c3, c4, c5, c6) \ 113 | (http_strcasecmp4(s1, c0, c1, c2, c3) && \ 114 | http_strcasecmp3(s1 + 4, c4, c5, c6)) 115 | 116 | #define http_strcasecmp8(s1, c0, c1, c2, c3, c4, c5, c6, c7) \ 117 | http_strcasecmp4(s1, c0, c1, c2, c3) && \ 118 | http_strcasecmp4(s1 + 4, c4, c5, c6, c7) 119 | 120 | #define http_strcasecmp9(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8) \ 121 | (http_strcasecmp4(s1, c0, c1, c2, c3) && \ 122 | http_strcasecmp4(s1 + 4, c4, c5, c6, c7) && http_toupper((s1)[8]) == c8) 123 | 124 | #define http_strcasecmp10(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) \ 125 | (http_strcasecmp5(s1, c0, c1, c2, c3, c4) && \ 126 | http_strcasecmp5(s1 + 5, c5, c6, c7, c8, c9)) 127 | 128 | #define http_strcasecmp11(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) \ 129 | (http_strcasecmp5(s1, c0, c1, c2, c3, c4) && \ 130 | http_strcasecmp6(s1 + 5, c5, c6, c7, c8, c9, c10)) 131 | 132 | #define http_strcasecmp13(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, \ 133 | c10, c11, c12) \ 134 | (http_strcasecmp6(s1, c0, c1, c2, c3, c4, c5) && \ 135 | http_strcasecmp7(s1 + 6, c6, c7, c8, c9, c10, c11, c12)) 136 | 137 | #define http_strcasecmp15(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, \ 138 | c10, c11, c12, c13, c14) \ 139 | (http_strcasecmp7(s1, c0, c1, c2, c3, c4, c5, c6) && \ 140 | http_strcasecmp8(s1 + 7, c7, c8, c9, c10, c11, c12, c13, c14)) 141 | 142 | #define http_strcasecmp18(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, \ 143 | c10, c11, c12, c13, c14, c15, c16, c17) \ 144 | (http_strcasecmp9(s1, c0, c1, c2, c3, c4, c5, c6, c7, c8) && \ 145 | http_strcasecmp9(s1 + 9, c9, c10, c11, c12, c13, c14, c15, c16, c17)) 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | log.c 20 | */ 21 | #define _GNU_SOURCE 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include "log.h" 34 | 35 | struct _log { 36 | int fd; 37 | char *file_path; 38 | int level; 39 | }; 40 | 41 | static char *log_levels[] = { 42 | [LOG_LEVEL_INFO] = "[INFO]: ", 43 | [LOG_LEVEL_WARN] = "[WARN]: ", 44 | [LOG_LEVEL_TRACE] = " [TRC]: ", 45 | [LOG_LEVEL_ERROR] = " [ERR]: ", 46 | [LOG_LEVEL_NOOP] = "[NOOP]: ", 47 | }; 48 | 49 | char log_fmt[1024] = {0}; 50 | 51 | static struct _log l = {0}; 52 | 53 | void 54 | log_(enum log_levels level, const char *module, const char *fmt, ...) 55 | { 56 | va_list arglist; 57 | if (level != LOG_LEVEL_ERROR && l.level < level) 58 | return; 59 | 60 | time_t now; 61 | time(&now); 62 | if (level == LOG_LEVEL_ERROR) 63 | strcpy(log_fmt, "\033[31m"); 64 | else 65 | strcpy(log_fmt, "\033[0m"); 66 | 67 | strcpy((char *)(log_fmt + strlen(log_fmt)), ctime(&now)); 68 | sprintf(log_fmt + strlen(log_fmt) - 5, " %-15s %s %s\n", module, log_levels[level], fmt); 69 | 70 | if (l.fd == -1) { 71 | va_start(arglist, fmt); 72 | vdprintf(2, log_fmt, arglist); 73 | va_end(arglist); 74 | return; 75 | } 76 | 77 | va_start(arglist, fmt); 78 | vdprintf(l.fd, log_fmt, arglist); 79 | va_end(arglist); 80 | } 81 | 82 | void 83 | log_set_level(enum log_levels level) 84 | { 85 | l.level = level; 86 | } 87 | 88 | void 89 | log_initialize(const char *path, enum log_levels level) 90 | { 91 | 92 | char log_path[1024] = {0}; 93 | sprintf(log_path, "%s/memqueue.log", path); 94 | 95 | l.level = level; 96 | l.fd = open(log_path, O_CREAT | O_APPEND | O_WRONLY, 0640); 97 | if (l.fd < 0) { 98 | warn("Cannot open file %s for logging", log_path); 99 | l.fd = 2; /* stderr */ 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | log.h 20 | */ 21 | #ifndef LOG_H_ 22 | #define LOG_H_ 23 | #include 24 | 25 | /* 26 | * logger functionalities 27 | */ 28 | enum log_levels { 29 | LOG_LEVEL_INFO, 30 | LOG_LEVEL_WARN, 31 | LOG_LEVEL_TRACE, 32 | LOG_LEVEL_ERROR, 33 | LOG_LEVEL_NOOP 34 | }; 35 | 36 | void log_(enum log_levels level, const char *module, 37 | const char *fmt, ...); 38 | 39 | void log_initialize(const char *path, enum log_levels level); 40 | 41 | void log_set_level(enum log_levels level); 42 | 43 | #define LOG(level, fmt, ...) \ 44 | do { \ 45 | log_(level, __FILE__, fmt, ##__VA_ARGS__); \ 46 | } while (0) \ 47 | 48 | #define LOG_WARN(fmt, ...) \ 49 | LOG(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) \ 50 | 51 | #define LOG_ERROR(fmt, ...) \ 52 | LOG(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) \ 53 | 54 | #define LOG_TRACE(fmt, ...) \ 55 | LOG(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) \ 56 | 57 | #define LOG_INFO(fmt, ...) \ 58 | LOG(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) \ 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | main.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #ifdef __FreeBSD__ 36 | #include 37 | #endif 38 | 39 | #include 40 | #include "http_str.h" 41 | #include "http.h" 42 | #include "http_bd.h" 43 | #include "sock_easy.h" 44 | #include "log.h" 45 | #include "time.h" 46 | #include "router.h" 47 | #include "memqueue.h" 48 | #define VERSION "1.0" 49 | 50 | #include 51 | 52 | static int 53 | handle_args (int argc, char **argv, lsn_t *lsn) 54 | { 55 | extern char *optarg; 56 | int c = 0; 57 | char *errmsg = NULL; 58 | int err = 0; 59 | 60 | const char *menu = \ 61 | "usage: express [options]\n" 62 | "-p : http listener port (default: 5556)\n" 63 | "-a : http listener IP address (default: 0.0.0.0)\n" 64 | "-i : http listener interface\n" 65 | "-h : print this help message and exits\n" 66 | "-t : set log path\n" 67 | "-l : set log level to info|error|trace\n"; 68 | 69 | lsn->lsn_port = 5556; 70 | 71 | while ((c = getopt(argc, argv, "l:hp:t:")) != -1) { 72 | switch(c) { 73 | case 'p': 74 | lsn->lsn_port = strtol(optarg, NULL, 10); 75 | if (lsn->lsn_port < 1) { 76 | errmsg = "port range is between 1 and 65535"; 77 | err = -1; 78 | goto done; 79 | } 80 | break; 81 | case 't': 82 | log_initialize(optarg, LOG_LEVEL_INFO); 83 | case 'l': 84 | if (strcasecmp(optarg, "error") == 0) 85 | log_set_level(LOG_LEVEL_ERROR); 86 | else if (strcasecmp(optarg, "warn") == 0) 87 | log_set_level(LOG_LEVEL_WARN); 88 | else if (strcasecmp(optarg, "trace") == 0) 89 | log_set_level(LOG_LEVEL_TRACE); 90 | else if (strcasecmp(optarg, "info") == 0) 91 | log_set_level(LOG_LEVEL_INFO); 92 | break; 93 | case 'h': 94 | default: 95 | err = -1; 96 | goto done; 97 | } 98 | } 99 | 100 | done: 101 | if (err == -1) { 102 | printf("%s", menu); 103 | if (errmsg) 104 | printf("ERROR: %s\n", errmsg); 105 | return err; 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | int lsn_fd = 0; 112 | 113 | int 114 | main(int argc, char *argv[]) 115 | { 116 | 117 | lsn_t lsn = {0}; 118 | struct sigaction act; 119 | act.sa_handler = SIG_IGN; 120 | 121 | /* the process by default exits on SIGPIPE, we don't want that */ 122 | signal(SIGPIPE, SIG_IGN); 123 | sigaction(SIGPIPE, &act, NULL); 124 | 125 | if (handle_args(argc, argv, &lsn) == -1) 126 | exit(1); 127 | 128 | http_route_init(); 129 | if (lsn_init(&lsn, http_route_handle_request) != 0) 130 | exit(1); 131 | 132 | 133 | lsn_fd = e_listener("127.0.0.1", lsn.lsn_port); 134 | memqueue_init(); 135 | lsn_run(&lsn); 136 | 137 | printf("Exiting...! %d\n", getpid()); 138 | 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /src/memqueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | memqueue.h 20 | */ 21 | #ifndef _MEMQUEUE_H_ 22 | #define _MEMQUEUE_H_ 23 | 24 | int memqueue_init(void); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/memqueue_expiry.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | memqueue_expiry.c 20 | */ 21 | #include 22 | #include "memqueue_impl.h" 23 | #include "time.h" 24 | 25 | static expiry_node_t* rb_search(struct rb_root *root, uint32_t msecs); 26 | static int rb_insert(struct rb_root *root, expiry_node_t *data); 27 | static void possibly_node_free(expiry_node_t **data, struct rb_root *root); 28 | 29 | static expiry_node_t* 30 | rb_search(struct rb_root *root, uint32_t msecs) 31 | { 32 | struct rb_node *node = root->rb_node; 33 | expiry_node_t *data = NULL; 34 | 35 | while (node) { 36 | data = container_of(node, expiry_node_t, node); 37 | 38 | if (msecs < data->msecs) 39 | node = node->rb_left; 40 | else if (msecs > data->msecs) 41 | node = node->rb_right; 42 | else 43 | return data; 44 | } 45 | 46 | return NULL; 47 | } 48 | 49 | static int 50 | rb_insert(struct rb_root *root, expiry_node_t *data) 51 | { 52 | expiry_node_t *this = NULL; 53 | struct rb_node **new = &(root->rb_node), *parent = NULL; 54 | 55 | while (*new) 56 | { 57 | parent = *new; 58 | this = container_of(parent, expiry_node_t, node); 59 | 60 | if (this->msecs > data->msecs) 61 | new = &((*new)->rb_left); 62 | else if (this->msecs < data->msecs) 63 | new = &((*new)->rb_right); 64 | else { 65 | assert(0); 66 | return -1; 67 | } 68 | } 69 | 70 | rb_link_node(&data->node, parent, new); 71 | rb_insert_color(&data->node, root); 72 | 73 | return 0; 74 | } 75 | 76 | void 77 | obj_sched_expire(memqueue_ins_t *ins, void *obj, uint32_t msecs, 78 | obj_type_t type) 79 | { 80 | expiry_node_t *tmp = NULL; 81 | struct rb_root *root = NULL; 82 | uint32_t t_diff_msecs = 0; 83 | int ret = 0; 84 | uint32_t min_timeout = sched_get_min_timeout(ins); 85 | 86 | if (type == MSG_TYPE) 87 | root = &ins->msg_expiry; 88 | else if (type == MEMQUEUE_TYPE) 89 | root = &ins->memqueue_expiry; 90 | else if (type == CONSUMER_TYPE) 91 | root = &ins->consumer_expiry; 92 | 93 | t_diff_msecs = tick_diff_msecs(ins->birth, rdtsc()) + msecs; 94 | tmp = rb_search(root, t_diff_msecs); 95 | 96 | /*printf("t_diff_msecs is %u, sched_get_min_timeout is %u, msecs is %u\n", 97 | t_diff_msecs, min_timeout, msecs);*/ 98 | 99 | if (min_timeout == 0 || min_timeout > msecs) 100 | lthread_cond_signal(ins->cond); 101 | 102 | if (tmp == NULL && 103 | (tmp = calloc(1, sizeof(expiry_node_t))) != NULL) { 104 | tmp->msecs = t_diff_msecs; 105 | ret = rb_insert(root, tmp); 106 | assert(ret != -1); 107 | 108 | if (type == MSG_TYPE) { 109 | LIST_INIT(&tmp->msg_objs); 110 | LIST_INSERT_HEAD(&tmp->msg_objs, (msg_t *)obj, expiry_next); 111 | ((msg_t *)obj)->expiry_node = tmp; 112 | } else if (type == MEMQUEUE_TYPE) { 113 | LIST_INIT(&tmp->memqueue_objs); 114 | LIST_INSERT_HEAD(&tmp->memqueue_objs, (memqueue_t *)obj, 115 | expiry_next); 116 | ((memqueue_t *)obj)->expiry_node = tmp; 117 | } else if (type == CONSUMER_TYPE) { 118 | LIST_INIT(&tmp->consumer_objs); 119 | LIST_INSERT_HEAD(&tmp->consumer_objs, (consumer_t *)obj, 120 | expiry_next); 121 | ((consumer_t *)obj)->expiry_node = tmp; 122 | } 123 | 124 | return; 125 | } 126 | 127 | if (tmp) { 128 | if (type == MSG_TYPE) 129 | LIST_INSERT_HEAD(&tmp->msg_objs, (msg_t *)obj, expiry_next); 130 | else if (type == MEMQUEUE_TYPE) 131 | LIST_INSERT_HEAD(&tmp->memqueue_objs, (memqueue_t *)obj, 132 | expiry_next); 133 | else if (type == CONSUMER_TYPE) 134 | LIST_INSERT_HEAD(&tmp->consumer_objs, (consumer_t *)obj, 135 | expiry_next); 136 | } else { 137 | assert(0); 138 | } 139 | 140 | } 141 | 142 | uint32_t 143 | sched_get_min_timeout(memqueue_ins_t *ins) 144 | { 145 | struct rb_root *roots[] = {&ins->msg_expiry, &ins->memqueue_expiry, 146 | &ins->consumer_expiry}; 147 | struct rb_node *node = NULL; 148 | expiry_node_t *data = NULL; 149 | uint32_t t_diff_msecs = 0, min = 0, msecs = 0; 150 | int i = 0; 151 | int found = 0; 152 | 153 | t_diff_msecs = tick_diff_msecs(ins->birth, rdtsc()); 154 | 155 | for (i = 0; i < 3; i++) { 156 | node = roots[i]->rb_node; 157 | while (node) { 158 | data = container_of(node, expiry_node_t, node); 159 | msecs = data->msecs; 160 | node = node->rb_left; 161 | found = 1; 162 | } 163 | 164 | if (!found) 165 | continue; 166 | 167 | //printf("min found i %d %d\n", i, msecs); 168 | 169 | if (msecs > t_diff_msecs) { 170 | if (min > (msecs - t_diff_msecs) || min == 0) 171 | min = msecs - t_diff_msecs; 172 | } else { 173 | return 1; 174 | } 175 | 176 | found = 0; 177 | } 178 | 179 | //printf("min is %d\n",min); 180 | 181 | return min; 182 | } 183 | 184 | void 185 | objs_expire(memqueue_ins_t *ins, obj_type_t type) 186 | { 187 | struct rb_root *root = NULL; 188 | uint32_t t_diff_msecs = 0; 189 | expiry_node_t *data = NULL; 190 | msg_t *msg = NULL; 191 | msg_t *msg_tmp = NULL; 192 | memqueue_t *memqueue = NULL; 193 | memqueue_t *memqueue_tmp = NULL; 194 | consumer_t *consumer = NULL; 195 | consumer_t *consumer_tmp = NULL; 196 | struct rb_node *node = NULL; 197 | 198 | if (type == MSG_TYPE) 199 | root = &ins->msg_expiry; 200 | else if (type == MEMQUEUE_TYPE) 201 | root = &ins->memqueue_expiry; 202 | else if (type == CONSUMER_TYPE) 203 | root = &ins->consumer_expiry; 204 | 205 | node = root->rb_node; 206 | 207 | t_diff_msecs = tick_diff_msecs(ins->birth, rdtsc()); 208 | 209 | while (node) { 210 | data = container_of(node, expiry_node_t, node); 211 | node = node->rb_left; 212 | 213 | if (data->msecs <= t_diff_msecs) { 214 | if (type == MSG_TYPE) { 215 | LIST_FOREACH_SAFE(msg, &data->msg_objs, expiry_next, msg_tmp) { 216 | LIST_REMOVE(msg, expiry_next); 217 | memqueue_msg_release(msg); 218 | msg->expiry_node = NULL; 219 | } 220 | } else if (type == MEMQUEUE_TYPE) { 221 | LIST_FOREACH_SAFE(memqueue, &data->memqueue_objs, expiry_next, 222 | memqueue_tmp) { 223 | LIST_REMOVE(memqueue, expiry_next); 224 | memqueue_release(memqueue); 225 | memqueue->expiry_node = NULL; 226 | } 227 | } else if (type == CONSUMER_TYPE) { 228 | LIST_FOREACH_SAFE(consumer, &data->consumer_objs, expiry_next, 229 | consumer_tmp) { 230 | LIST_REMOVE(consumer, expiry_next); 231 | consumer_expired(consumer); 232 | consumer->expiry_node = NULL; 233 | } 234 | } 235 | 236 | possibly_node_free(&data, root); 237 | } 238 | } 239 | } 240 | 241 | void 242 | memqueue_resched(memqueue_ins_t *ins, memqueue_t *memqueue) 243 | { 244 | 245 | if (!memqueue->expiry_node) 246 | return; 247 | 248 | LIST_REMOVE(memqueue, expiry_next); 249 | possibly_node_free(&memqueue->expiry_node, &ins->memqueue_expiry); 250 | 251 | obj_sched_expire(ins, memqueue, memqueue->expiry, MEMQUEUE_TYPE); 252 | } 253 | 254 | void 255 | consumer_resched(memqueue_ins_t *ins, consumer_t *consumer) 256 | { 257 | 258 | if (!consumer->expiry_node) 259 | return; 260 | 261 | LIST_REMOVE(consumer, expiry_next); 262 | possibly_node_free(&consumer->expiry_node, &ins->consumer_expiry); 263 | 264 | obj_sched_expire(ins, consumer, consumer->expiry, CONSUMER_TYPE); 265 | } 266 | 267 | static void 268 | possibly_node_free(expiry_node_t **data, struct rb_root *root) 269 | { 270 | if (LIST_EMPTY(&(*data)->memqueue_objs) && 271 | LIST_EMPTY(&(*data)->msg_objs) && 272 | LIST_EMPTY(&(*data)->consumer_objs)) { 273 | rb_erase(&(*data)->node, root); 274 | free(*data); 275 | *data = NULL; 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/memqueue_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | memqueue_impl.h 20 | */ 21 | #ifndef _MEMQUEUE_H_ 22 | #define _MEMQUEUE_H_ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include "http.h" 29 | #include "hash.h" 30 | #include "rbtree.h" 31 | #include "time.h" 32 | #include "json/json.h" 33 | 34 | struct expiry_node; 35 | struct cli_binder; 36 | struct msg; 37 | struct memqueue; 38 | struct pending_msg; 39 | struct memqueue_ins; 40 | struct consumer; 41 | 42 | typedef struct expiry_node expiry_node_t; 43 | typedef struct cli_binder cli_binder_t; 44 | typedef struct msg msg_t; 45 | typedef struct memqueue memqueue_t; 46 | typedef struct memqueue_binder memqueue_binder_t; 47 | typedef struct pending_msg pending_msg_t; 48 | typedef struct memqueue_ins memqueue_ins_t; 49 | typedef struct consumer consumer_t; 50 | 51 | LIST_HEAD(cli_binder_l, cli_binder); 52 | LIST_HEAD(consumer_l, consumer); 53 | LIST_HEAD(msg_l, msg); 54 | LIST_HEAD(memqueue_l, memqueue); 55 | LIST_HEAD(memqueue_binder_l, memqueue_binder); 56 | TAILQ_HEAD(msg_q, msg); 57 | TAILQ_HEAD(pending_msg_q, pending_msg); 58 | 59 | typedef struct expiry_obj_l expiry_obj_l_t; 60 | typedef struct cli_binder_l cli_binder_l_t; 61 | typedef struct msg_q msg_q_t; 62 | typedef struct msg_l msg_l_t; 63 | typedef struct consumer_l consumer_l_t; 64 | typedef struct memqueue_l memqueue_l_t; 65 | typedef struct memqueue_binder_l memqueue_binder_l_t; 66 | typedef struct pending_msg_q pending_msg_q_t; 67 | 68 | typedef enum { 69 | MEMQUEUE_NOT_FOUND = 0, 70 | MEMQUEUE_CREATED, 71 | MEMQUEUE_EXISTS, 72 | MEMQUEUE_MSG_ADDED, 73 | MEMQUEUE_MSGS, 74 | MEMQUEUE_QUEUE_INFO, 75 | MEMQUEUE_TIMEOUT, 76 | MEMQUEUE_DELETED, 77 | MEMQUEUE_FULL, 78 | MEMQUEUE_OK, 79 | } memqueue_ret_t; 80 | 81 | typedef enum { 82 | MSG_TYPE, 83 | MEMQUEUE_TYPE, 84 | CONSUMER_TYPE, 85 | } obj_type_t; 86 | 87 | struct expiry_node { 88 | uint32_t msecs; 89 | struct rb_node node; 90 | memqueue_l_t memqueue_objs; 91 | consumer_l_t consumer_objs; 92 | msg_l_t msg_objs; 93 | }; 94 | 95 | /* 96 | * memqueue_binder represents a bind to a queue. 97 | */ 98 | struct memqueue_binder { 99 | int rev; 100 | memqueue_t *memqueue; 101 | LIST_ENTRY(memqueue_binder) q_next; /* link list in memqeueue */ 102 | LIST_ENTRY(memqueue_binder) b_next; /* link list in cli_binder */ 103 | cli_binder_t *cli_binder; 104 | int include_consumers; 105 | }; 106 | 107 | struct pending_msg { 108 | msg_t *msg; 109 | memqueue_binder_t memqueue_binder; 110 | TAILQ_ENTRY(pending_msg) next; 111 | }; 112 | 113 | struct cli_binder { 114 | lthread_t *lt; 115 | uint32_t timeout; 116 | lthread_cond_t *cond; 117 | memqueue_binder_l_t memqueues; 118 | LIST_ENTRY(cli_binder) next; 119 | pending_msg_q_t pending_msgs; 120 | }; 121 | 122 | struct msg { 123 | void *data; 124 | uint64_t data_len; 125 | int ref_count; 126 | int rev; 127 | int new; 128 | memqueue_t *memqueue; 129 | LIST_ENTRY(msg) expiry_next; 130 | TAILQ_ENTRY(msg) next; 131 | int32_t expiry; 132 | expiry_node_t *expiry_node; 133 | uint64_t msg_id; 134 | }; 135 | 136 | struct memqueue { 137 | int rev; 138 | int ref_count; 139 | int max_size; 140 | int drop_from_head; 141 | char *q_id; 142 | msg_q_t msg_queue; 143 | memqueue_binder_l_t memqueue_binders; 144 | LIST_ENTRY(memqueue) expiry_next; 145 | uint32_t expiry; 146 | uint32_t consumer_expiry; 147 | h_hash_t *consumers; 148 | expiry_node_t *expiry_node; 149 | int msgs_in_queue; 150 | }; 151 | 152 | struct memqueue_ins { 153 | h_hash_t *queue_store; 154 | uint64_t birth; 155 | struct rb_root memqueue_expiry; 156 | struct rb_root msg_expiry; 157 | struct rb_root consumer_expiry; 158 | lthread_cond_t *cond; 159 | lthread_t *lt_sleep; 160 | uint64_t unique_msg_id; 161 | 162 | }; 163 | 164 | struct consumer { 165 | char *consumer_id; 166 | uint32_t expiry; 167 | expiry_node_t *expiry_node; 168 | memqueue_t *memqueue; 169 | LIST_ENTRY(consumer) expiry_next; 170 | }; 171 | 172 | #define VERSION "memqueue 1.0" 173 | #define set_server_header (http_add_header(cli, "Server", VERSION)) 174 | 175 | #define json_str(x) json_object_new_string((x)) 176 | 177 | void memqueue_release(memqueue_t *q); 178 | void memqueue_msg_release(msg_t *msg); 179 | void obj_sched_expire(memqueue_ins_t *ins, void *obj, uint32_t msecs, 180 | obj_type_t type); 181 | uint32_t sched_get_min_timeout(memqueue_ins_t *ins); 182 | void objs_expire(memqueue_ins_t *ins, obj_type_t type); 183 | void memqueue_resched(memqueue_ins_t *ins, memqueue_t *memqueue); 184 | void consumer_resched(memqueue_ins_t *ins, consumer_t *consumer); 185 | void consumer_expired(consumer_t *consumer); 186 | #endif 187 | -------------------------------------------------------------------------------- /src/rbtree.c: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | (C) 2002 David Woodhouse 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | linux/lib/rbtree.c 21 | */ 22 | 23 | #include "rbtree.h" 24 | 25 | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 26 | { 27 | struct rb_node *right = node->rb_right; 28 | struct rb_node *parent = rb_parent(node); 29 | 30 | if ((node->rb_right = right->rb_left)) 31 | rb_set_parent(right->rb_left, node); 32 | right->rb_left = node; 33 | 34 | rb_set_parent(right, parent); 35 | 36 | if (parent) 37 | { 38 | if (node == parent->rb_left) 39 | parent->rb_left = right; 40 | else 41 | parent->rb_right = right; 42 | } 43 | else 44 | root->rb_node = right; 45 | rb_set_parent(node, right); 46 | } 47 | 48 | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 49 | { 50 | struct rb_node *left = node->rb_left; 51 | struct rb_node *parent = rb_parent(node); 52 | 53 | if ((node->rb_left = left->rb_right)) 54 | rb_set_parent(left->rb_right, node); 55 | left->rb_right = node; 56 | 57 | rb_set_parent(left, parent); 58 | 59 | if (parent) 60 | { 61 | if (node == parent->rb_right) 62 | parent->rb_right = left; 63 | else 64 | parent->rb_left = left; 65 | } 66 | else 67 | root->rb_node = left; 68 | rb_set_parent(node, left); 69 | } 70 | 71 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 72 | { 73 | struct rb_node *parent, *gparent; 74 | 75 | while ((parent = rb_parent(node)) && rb_is_red(parent)) 76 | { 77 | gparent = rb_parent(parent); 78 | 79 | if (parent == gparent->rb_left) 80 | { 81 | { 82 | register struct rb_node *uncle = gparent->rb_right; 83 | if (uncle && rb_is_red(uncle)) 84 | { 85 | rb_set_black(uncle); 86 | rb_set_black(parent); 87 | rb_set_red(gparent); 88 | node = gparent; 89 | continue; 90 | } 91 | } 92 | 93 | if (parent->rb_right == node) 94 | { 95 | register struct rb_node *tmp; 96 | __rb_rotate_left(parent, root); 97 | tmp = parent; 98 | parent = node; 99 | node = tmp; 100 | } 101 | 102 | rb_set_black(parent); 103 | rb_set_red(gparent); 104 | __rb_rotate_right(gparent, root); 105 | } else { 106 | { 107 | register struct rb_node *uncle = gparent->rb_left; 108 | if (uncle && rb_is_red(uncle)) 109 | { 110 | rb_set_black(uncle); 111 | rb_set_black(parent); 112 | rb_set_red(gparent); 113 | node = gparent; 114 | continue; 115 | } 116 | } 117 | 118 | if (parent->rb_left == node) 119 | { 120 | register struct rb_node *tmp; 121 | __rb_rotate_right(parent, root); 122 | tmp = parent; 123 | parent = node; 124 | node = tmp; 125 | } 126 | 127 | rb_set_black(parent); 128 | rb_set_red(gparent); 129 | __rb_rotate_left(gparent, root); 130 | } 131 | } 132 | 133 | rb_set_black(root->rb_node); 134 | } 135 | 136 | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 137 | struct rb_root *root) 138 | { 139 | struct rb_node *other; 140 | 141 | while ((!node || rb_is_black(node)) && node != root->rb_node) 142 | { 143 | if (parent->rb_left == node) 144 | { 145 | other = parent->rb_right; 146 | if (rb_is_red(other)) 147 | { 148 | rb_set_black(other); 149 | rb_set_red(parent); 150 | __rb_rotate_left(parent, root); 151 | other = parent->rb_right; 152 | } 153 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 154 | (!other->rb_right || rb_is_black(other->rb_right))) 155 | { 156 | rb_set_red(other); 157 | node = parent; 158 | parent = rb_parent(node); 159 | } 160 | else 161 | { 162 | if (!other->rb_right || rb_is_black(other->rb_right)) 163 | { 164 | rb_set_black(other->rb_left); 165 | rb_set_red(other); 166 | __rb_rotate_right(other, root); 167 | other = parent->rb_right; 168 | } 169 | rb_set_color(other, rb_color(parent)); 170 | rb_set_black(parent); 171 | rb_set_black(other->rb_right); 172 | __rb_rotate_left(parent, root); 173 | node = root->rb_node; 174 | break; 175 | } 176 | } 177 | else 178 | { 179 | other = parent->rb_left; 180 | if (rb_is_red(other)) 181 | { 182 | rb_set_black(other); 183 | rb_set_red(parent); 184 | __rb_rotate_right(parent, root); 185 | other = parent->rb_left; 186 | } 187 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 188 | (!other->rb_right || rb_is_black(other->rb_right))) 189 | { 190 | rb_set_red(other); 191 | node = parent; 192 | parent = rb_parent(node); 193 | } 194 | else 195 | { 196 | if (!other->rb_left || rb_is_black(other->rb_left)) 197 | { 198 | rb_set_black(other->rb_right); 199 | rb_set_red(other); 200 | __rb_rotate_left(other, root); 201 | other = parent->rb_left; 202 | } 203 | rb_set_color(other, rb_color(parent)); 204 | rb_set_black(parent); 205 | rb_set_black(other->rb_left); 206 | __rb_rotate_right(parent, root); 207 | node = root->rb_node; 208 | break; 209 | } 210 | } 211 | } 212 | if (node) 213 | rb_set_black(node); 214 | } 215 | 216 | void rb_erase(struct rb_node *node, struct rb_root *root) 217 | { 218 | struct rb_node *child, *parent; 219 | int color; 220 | 221 | if (!node->rb_left) 222 | child = node->rb_right; 223 | else if (!node->rb_right) 224 | child = node->rb_left; 225 | else 226 | { 227 | struct rb_node *old = node, *left; 228 | 229 | node = node->rb_right; 230 | while ((left = node->rb_left) != NULL) 231 | node = left; 232 | 233 | if (rb_parent(old)) { 234 | if (rb_parent(old)->rb_left == old) 235 | rb_parent(old)->rb_left = node; 236 | else 237 | rb_parent(old)->rb_right = node; 238 | } else 239 | root->rb_node = node; 240 | 241 | child = node->rb_right; 242 | parent = rb_parent(node); 243 | color = rb_color(node); 244 | 245 | if (parent == old) { 246 | parent = node; 247 | } else { 248 | if (child) 249 | rb_set_parent(child, parent); 250 | parent->rb_left = child; 251 | 252 | node->rb_right = old->rb_right; 253 | rb_set_parent(old->rb_right, node); 254 | } 255 | 256 | node->rb_parent_color = old->rb_parent_color; 257 | node->rb_left = old->rb_left; 258 | rb_set_parent(old->rb_left, node); 259 | 260 | goto color; 261 | } 262 | 263 | parent = rb_parent(node); 264 | color = rb_color(node); 265 | 266 | if (child) 267 | rb_set_parent(child, parent); 268 | if (parent) 269 | { 270 | if (parent->rb_left == node) 271 | parent->rb_left = child; 272 | else 273 | parent->rb_right = child; 274 | } 275 | else 276 | root->rb_node = child; 277 | 278 | color: 279 | if (color == RB_BLACK) 280 | __rb_erase_color(child, parent, root); 281 | } 282 | 283 | struct rb_node *rb_last(const struct rb_root *root) 284 | { 285 | struct rb_node *n; 286 | 287 | n = root->rb_node; 288 | if (!n) 289 | return NULL; 290 | while (n->rb_right) 291 | n = n->rb_right; 292 | return n; 293 | } 294 | 295 | struct rb_node *rb_next(const struct rb_node *node) 296 | { 297 | struct rb_node *parent; 298 | 299 | if (rb_parent(node) == node) 300 | return NULL; 301 | 302 | /* If we have a right-hand child, go down and then left as far 303 | as we can. */ 304 | if (node->rb_right) { 305 | node = node->rb_right; 306 | while (node->rb_left) 307 | node=node->rb_left; 308 | return (struct rb_node *)node; 309 | } 310 | 311 | /* No right-hand children. Everything down and left is 312 | smaller than us, so any 'next' node must be in the general 313 | direction of our parent. Go up the tree; any time the 314 | ancestor is a right-hand child of its parent, keep going 315 | up. First time it's a left-hand child of its parent, said 316 | parent is our 'next' node. */ 317 | while ((parent = rb_parent(node)) && node == parent->rb_right) 318 | node = parent; 319 | 320 | return parent; 321 | } 322 | 323 | struct rb_node *rb_prev(const struct rb_node *node) 324 | { 325 | struct rb_node *parent; 326 | 327 | if (rb_parent(node) == node) 328 | return NULL; 329 | 330 | /* If we have a left-hand child, go down and then right as far 331 | as we can. */ 332 | if (node->rb_left) { 333 | node = node->rb_left; 334 | while (node->rb_right) 335 | node=node->rb_right; 336 | return (struct rb_node *)node; 337 | } 338 | 339 | /* No left-hand children. Go up till we find an ancestor which 340 | is a right-hand child of its parent */ 341 | while ((parent = rb_parent(node)) && node == parent->rb_left) 342 | node = parent; 343 | 344 | return parent; 345 | } 346 | 347 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 348 | struct rb_root *root) 349 | { 350 | struct rb_node *parent = rb_parent(victim); 351 | 352 | /* Set the surrounding nodes to point to the replacement */ 353 | if (parent) { 354 | if (victim == parent->rb_left) 355 | parent->rb_left = new; 356 | else 357 | parent->rb_right = new; 358 | } else { 359 | root->rb_node = new; 360 | } 361 | if (victim->rb_left) 362 | rb_set_parent(victim->rb_left, new); 363 | if (victim->rb_right) 364 | rb_set_parent(victim->rb_right, new); 365 | 366 | /* Copy the pointers/colour from the victim to the replacement */ 367 | *new = *victim; 368 | } 369 | -------------------------------------------------------------------------------- /src/rbtree.h: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | linux/include/linux/rbtree.h 20 | 21 | To use rbtrees you'll have to implement your own insert and search cores. 22 | This will avoid us to use callbacks and to drop drammatically performances. 23 | I know it's not the cleaner way, but in C (not in C++) to get 24 | performances and genericity... 25 | 26 | Some example of insert and search follows here. The search is a plain 27 | normal search over an ordered tree. The insert instead must be implemented 28 | in two steps: First, the code must insert the element in order as a red leaf 29 | in the tree, and then the support library function rb_insert_color() must 30 | be called. Such function will do the not trivial work to rebalance the 31 | rbtree, if necessary. 32 | 33 | ----------------------------------------------------------------------- 34 | static inline struct page * rb_search_page_cache(struct inode * inode, 35 | unsigned long offset) 36 | { 37 | struct rb_node * n = inode->i_rb_page_cache.rb_node; 38 | struct page * page; 39 | 40 | while (n) 41 | { 42 | page = rb_entry(n, struct page, rb_page_cache); 43 | 44 | if (offset < page->offset) 45 | n = n->rb_left; 46 | else if (offset > page->offset) 47 | n = n->rb_right; 48 | else 49 | return page; 50 | } 51 | return NULL; 52 | } 53 | 54 | static inline struct page * __rb_insert_page_cache(struct inode * inode, 55 | unsigned long offset, 56 | struct rb_node * node) 57 | { 58 | struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 59 | struct rb_node * parent = NULL; 60 | struct page * page; 61 | 62 | while (*p) 63 | { 64 | parent = *p; 65 | page = rb_entry(parent, struct page, rb_page_cache); 66 | 67 | if (offset < page->offset) 68 | p = &(*p)->rb_left; 69 | else if (offset > page->offset) 70 | p = &(*p)->rb_right; 71 | else 72 | return page; 73 | } 74 | 75 | rb_link_node(node, parent, p); 76 | 77 | return NULL; 78 | } 79 | 80 | static inline struct page * rb_insert_page_cache(struct inode * inode, 81 | unsigned long offset, 82 | struct rb_node * node) 83 | { 84 | struct page * ret; 85 | if ((ret = __rb_insert_page_cache(inode, offset, node))) 86 | goto out; 87 | rb_insert_color(node, &inode->i_rb_page_cache); 88 | out: 89 | return ret; 90 | } 91 | ----------------------------------------------------------------------- 92 | */ 93 | 94 | #ifndef _RBTREE_H 95 | #define _RBTREE_H 96 | #include 97 | 98 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 99 | 100 | #define container_of(ptr, type, member) ({ \ 101 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 102 | (type *)( (char *)__mptr - offsetof(type,member) );}) 103 | 104 | 105 | struct rb_node 106 | { 107 | unsigned long rb_parent_color; 108 | #define RB_RED 0 109 | #define RB_BLACK 1 110 | struct rb_node *rb_right; 111 | struct rb_node *rb_left; 112 | } __attribute__((aligned(sizeof(long)))); 113 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 114 | 115 | struct rb_root 116 | { 117 | struct rb_node *rb_node; 118 | }; 119 | 120 | 121 | #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 122 | #define rb_color(r) ((r)->rb_parent_color & 1) 123 | #define rb_is_red(r) (!rb_color(r)) 124 | #define rb_is_black(r) rb_color(r) 125 | #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 126 | #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 127 | 128 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 129 | { 130 | rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 131 | } 132 | static inline void rb_set_color(struct rb_node *rb, int color) 133 | { 134 | rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 135 | } 136 | 137 | #define RB_ROOT (struct rb_root) { NULL, } 138 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 139 | 140 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 141 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 142 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 143 | 144 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 145 | extern void rb_erase(struct rb_node *, struct rb_root *); 146 | 147 | typedef void (*rb_augment_f)(struct rb_node *node, void *data); 148 | 149 | extern void rb_augment_insert(struct rb_node *node, 150 | rb_augment_f func, void *data); 151 | extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 152 | extern void rb_augment_erase_end(struct rb_node *node, 153 | rb_augment_f func, void *data); 154 | 155 | /* Find logical next and previous nodes in a tree */ 156 | extern struct rb_node *rb_next(const struct rb_node *); 157 | extern struct rb_node *rb_prev(const struct rb_node *); 158 | extern struct rb_node *rb_first(const struct rb_root *); 159 | extern struct rb_node *rb_last(const struct rb_root *); 160 | 161 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 162 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 163 | struct rb_root *root); 164 | 165 | static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 166 | struct rb_node ** rb_link) 167 | { 168 | node->rb_parent_color = (unsigned long )parent; 169 | node->rb_left = node->rb_right = NULL; 170 | 171 | *rb_link = node; 172 | } 173 | 174 | #endif /* _LINUX_RBTREE_H */ 175 | -------------------------------------------------------------------------------- /src/router.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | router.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "router.h" 27 | #include "log.h" 28 | 29 | struct http_route { 30 | char *path; 31 | char *method; 32 | route_cb_t cb; 33 | pcre *re; 34 | LIST_ENTRY(http_route) next; 35 | }; 36 | typedef struct http_route http_route_t; 37 | 38 | LIST_HEAD(http_route_l, http_route); 39 | struct http_route_l routes; 40 | 41 | void 42 | http_route_init(void) 43 | { 44 | LIST_INIT(&routes); 45 | } 46 | 47 | int 48 | http_route_on(char *method, char *path, route_cb_t cb) 49 | { 50 | http_route_t *route = NULL; 51 | int erroffset = 0; 52 | const char *error = NULL; 53 | 54 | if ((route = malloc(sizeof(http_route_t))) == NULL) 55 | return -1; 56 | 57 | route->path = path; 58 | route->cb = cb; 59 | route->method = method; 60 | route->re = pcre_compile(path, 0, &error, &erroffset, NULL); 61 | if (route->re == NULL) { 62 | LOG_ERROR("PCRE compilation failed at offset %d: %s", erroffset, error); 63 | free(route); 64 | return -1; 65 | } 66 | LOG_INFO("Route %s added successfully", path); 67 | 68 | LIST_INSERT_HEAD(&routes, route, next); 69 | return 0; 70 | } 71 | 72 | int 73 | http_route_handle_request(void) 74 | { 75 | http_route_t *route = NULL; 76 | h_hash_t *h = NULL; 77 | int rc, i; 78 | int namecount; 79 | int ovector[30]; 80 | char *name_table = NULL; 81 | int name_entry_size; 82 | int matched = 0; 83 | char *path = http_get_path(); 84 | int ret = 0; 85 | 86 | LIST_FOREACH(route, &routes, next) { 87 | if (strcmp(route->method, http_get_method_str()) != 0) 88 | continue; 89 | rc = pcre_exec(route->re, NULL, path, 90 | strlen(path), 0, 0, ovector, 30); 91 | if (rc < 0) /* match failed. continue */ 92 | continue; 93 | 94 | matched = 1; 95 | rc = pcre_fullinfo(route->re, NULL, PCRE_INFO_NAMECOUNT, &namecount); 96 | /* group subpatterns exist, hand them off to the caller */ 97 | if (namecount > 0) { 98 | pcre_fullinfo(route->re, NULL, PCRE_INFO_NAMETABLE, &name_table); 99 | pcre_fullinfo(route->re, NULL, PCRE_INFO_NAMEENTRYSIZE, 100 | &name_entry_size); 101 | h = h_init(128); 102 | if (h != NULL) 103 | for (i = 0; i < namecount; i++) { 104 | int n = (name_table[0] << 8) | name_table[1]; 105 | char *value = strndup(path + ovector[2*n], 106 | ovector[2*n+1] - ovector[2*n]); 107 | if (value == NULL) { 108 | free(h); 109 | continue; 110 | } 111 | h_insert(h, name_table + 2, value); 112 | name_table += name_entry_size; 113 | } 114 | } 115 | 116 | ret = route->cb(h); 117 | if (h) { 118 | h_item_t *item = NULL; 119 | while ((item = h_next(h))) 120 | free(item->value); 121 | h_free(h); 122 | } 123 | 124 | if (ret == -2) 125 | continue; 126 | 127 | return ret; 128 | } 129 | 130 | if (!matched) { 131 | http_set_respcode(404); 132 | return -1; 133 | } 134 | 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /src/router.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | router.h 20 | */ 21 | #ifndef _ROUTE_H_ 22 | #define _ROUTE_H_ 23 | 24 | #include "http.h" 25 | 26 | typedef int (*route_cb_t)(h_hash_t *path_args); 27 | void http_route_init(void); 28 | int http_route_on(char *method, char *path, route_cb_t cb); 29 | int http_route_handle_request(void); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/sock_easy.c: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | sock_easy.c 20 | */ 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | int 30 | e_listener(char *ip, short port) 31 | { 32 | int fd = 0, ret = 0; 33 | int opt = 1; 34 | struct sockaddr_in sin; 35 | 36 | fd = lthread_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 37 | if (!fd) 38 | return -1; 39 | 40 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt,sizeof(int)) == -1) 41 | perror("failed to set SOREUSEADDR on socket"); 42 | 43 | memset(&sin, 0, sizeof(sin)); 44 | sin.sin_family = PF_INET; 45 | sin.sin_addr.s_addr = INADDR_ANY; 46 | sin.sin_port = htons(port); 47 | ret = bind(fd, (struct sockaddr *)&sin, sizeof(sin)); 48 | if (ret == -1) { 49 | close(fd); 50 | perror("cannot bind socket. closing.\n"); 51 | return -1; 52 | } 53 | ret = listen(fd, 2000); 54 | if (ret == -1) { 55 | close(fd); 56 | perror("cannot listen on socket. closing.\n"); 57 | return -1; 58 | } 59 | 60 | return fd; 61 | } 62 | 63 | int 64 | e_local_listener(char *path) 65 | { 66 | int fd = 0, ret = 0; 67 | struct sockaddr_un name; 68 | 69 | fd = lthread_socket(PF_LOCAL, SOCK_STREAM, 0); 70 | if (!fd) 71 | return -1; 72 | 73 | memset(&name, 0, sizeof(name)); 74 | name.sun_family = PF_LOCAL; 75 | strncpy(name.sun_path, path, sizeof (name.sun_path)); 76 | name.sun_path[strlen(path) + 1] = '\0'; 77 | ret = bind(fd, (struct sockaddr *)&name, SUN_LEN(&name)); 78 | if (ret == -1) { 79 | close(fd); 80 | perror("cannot bind socket. closing.\n"); 81 | return -1; 82 | } 83 | ret = listen(fd, 1500); 84 | if (ret == -1) { 85 | close(fd); 86 | perror("cannot listen on socket. closing.\n"); 87 | return -1; 88 | } 89 | 90 | return fd; 91 | } 92 | 93 | int 94 | e_local_connect(char *path) 95 | { 96 | int fd = 0; 97 | struct sockaddr_un name; 98 | 99 | fd = lthread_socket(PF_LOCAL, SOCK_STREAM, 0); 100 | if (!fd) 101 | return -1; 102 | 103 | memset(&name, 0, sizeof(name)); 104 | name.sun_family = PF_LOCAL; 105 | strncpy(name.sun_path, path, sizeof (name.sun_path)); 106 | name.sun_path[sizeof (name.sun_path) - 1] = '\0'; 107 | 108 | lthread_connect(fd, (struct sockaddr *)&name, SUN_LEN(&name), 1); 109 | 110 | return fd; 111 | } 112 | -------------------------------------------------------------------------------- /src/sock_easy.h: -------------------------------------------------------------------------------- 1 | /* 2 | memqueue 3 | (C) 2011 Hasan Alayli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | sock_easy.h 20 | */ 21 | int e_listener(char *ip, short port); 22 | -------------------------------------------------------------------------------- /src/time.c: -------------------------------------------------------------------------------- 1 | #include "time.h" 2 | 3 | uint64_t 4 | tick_diff_usecs(uint64_t t1, uint64_t t2) 5 | { 6 | uint64_t t3 = 0; 7 | t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 8 | return t3; 9 | } 10 | 11 | uint64_t 12 | tick_diff_msecs(uint64_t t1, uint64_t t2) 13 | { 14 | uint64_t t3 = 0; 15 | t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 16 | return t3/1000; 17 | } 18 | 19 | uint64_t 20 | tick_diff_secs(uint64_t t1, uint64_t t2) 21 | { 22 | uint64_t t3 = ((long double)(t2 - t1)/2793008320u) * 1000000u; 23 | return t3/1000000; 24 | } 25 | 26 | uint64_t 27 | rdtsc(void) 28 | { 29 | uint32_t a = 0, d = 0; 30 | 31 | asm volatile ("rdtsc" : "=a"(a), "=d"(d)); 32 | return (((uint64_t) d << 32) | a); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/time.h: -------------------------------------------------------------------------------- 1 | #ifndef _LT_TIME_ 2 | #define _LT_TIME_ 3 | #include 4 | 5 | uint64_t tick_diff_usecs(uint64_t t1, uint64_t t2); 6 | uint64_t tick_diff_msecs(uint64_t t1, uint64_t t2); 7 | uint64_t tick_diff_secs(uint64_t t1, uint64_t t2); 8 | uint64_t rdtsc(void); 9 | 10 | #endif 11 | --------------------------------------------------------------------------------