1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-06-16 06:15:24 +00:00

Brendan was getting pissed off about inconsistent indentation styles.

Convert all tabs to 4 spaces. All code must now use 4 space indents.

svn path=/trunk/avl/; revision=4492
This commit is contained in:
Michael Smith 2003-03-15 02:10:19 +00:00
parent 6198c728e1
commit d0cf9fe000
13 changed files with 1530 additions and 1530 deletions

758
avl/avl.c

File diff suppressed because it is too large Load Diff

108
avl/avl.h
View File

@ -2,7 +2,7 @@
* Copyright (C) 1995 by Sam Rushing <rushing@nightmare.com> * Copyright (C) 1995 by Sam Rushing <rushing@nightmare.com>
*/ */
/* $Id: avl.h,v 1.5 2003/03/09 22:56:46 karl Exp $ */ /* $Id: avl.h,v 1.6 2003/03/15 02:10:18 msmith Exp $ */
#ifndef __AVL_H #ifndef __AVL_H
#define __AVL_H #define __AVL_H
@ -22,24 +22,24 @@ extern "C" {
#endif #endif
typedef struct avl_node_tag { typedef struct avl_node_tag {
void * key; void * key;
struct avl_node_tag * left; struct avl_node_tag * left;
struct avl_node_tag * right; struct avl_node_tag * right;
struct avl_node_tag * parent; struct avl_node_tag * parent;
/* /*
* The lower 2 bits of <rank_and_balance> specify the balance * The lower 2 bits of <rank_and_balance> specify the balance
* factor: 00==-1, 01==0, 10==+1. * factor: 00==-1, 01==0, 10==+1.
* The rest of the bits are used for <rank> * The rest of the bits are used for <rank>
*/ */
unsigned long rank_and_balance; unsigned long rank_and_balance;
#ifndef NO_THREAD #ifndef NO_THREAD
rwlock_t rwlock; rwlock_t rwlock;
#endif #endif
} avl_node; } avl_node;
#define AVL_GET_BALANCE(n) ((int)(((n)->rank_and_balance & 3) - 1)) #define AVL_GET_BALANCE(n) ((int)(((n)->rank_and_balance & 3) - 1))
#define AVL_GET_RANK(n) (((n)->rank_and_balance >> 2)) #define AVL_GET_RANK(n) (((n)->rank_and_balance >> 2))
#define AVL_SET_BALANCE(n,b) \ #define AVL_SET_BALANCE(n,b) \
((n)->rank_and_balance) = \ ((n)->rank_and_balance) = \
@ -51,11 +51,11 @@ typedef struct avl_node_tag {
struct _avl_tree; struct _avl_tree;
typedef int (*avl_key_compare_fun_type) (void * compare_arg, void * a, void * b); typedef int (*avl_key_compare_fun_type) (void * compare_arg, void * a, void * b);
typedef int (*avl_iter_fun_type) (void * key, void * iter_arg); typedef int (*avl_iter_fun_type) (void * key, void * iter_arg);
typedef int (*avl_iter_index_fun_type) (unsigned long index, void * key, void * iter_arg); typedef int (*avl_iter_index_fun_type) (unsigned long index, void * key, void * iter_arg);
typedef int (*avl_free_key_fun_type) (void * key); typedef int (*avl_free_key_fun_type) (void * key);
typedef int (*avl_key_printer_fun_type) (char *, void *); typedef int (*avl_key_printer_fun_type) (char *, void *);
/* /*
* <compare_fun> and <compare_arg> let us associate a particular compare * <compare_fun> and <compare_arg> let us associate a particular compare
@ -63,11 +63,11 @@ typedef int (*avl_key_printer_fun_type) (char *, void *);
*/ */
typedef struct _avl_tree { typedef struct _avl_tree {
avl_node * root; avl_node * root;
unsigned long height; unsigned long height;
unsigned long length; unsigned long length;
avl_key_compare_fun_type compare_fun; avl_key_compare_fun_type compare_fun;
void * compare_arg; void * compare_arg;
#ifndef NO_THREAD #ifndef NO_THREAD
rwlock_t rwlock; rwlock_t rwlock;
#endif #endif
@ -77,66 +77,66 @@ avl_tree * avl_tree_new (avl_key_compare_fun_type compare_fun, void * compare_ar
avl_node * avl_node_new (void * key, avl_node * parent); avl_node * avl_node_new (void * key, avl_node * parent);
void avl_tree_free ( void avl_tree_free (
avl_tree * tree, avl_tree * tree,
avl_free_key_fun_type free_key_fun avl_free_key_fun_type free_key_fun
); );
int avl_insert ( int avl_insert (
avl_tree * ob, avl_tree * ob,
void * key void * key
); );
int avl_delete ( int avl_delete (
avl_tree * tree, avl_tree * tree,
void * key, void * key,
avl_free_key_fun_type free_key_fun avl_free_key_fun_type free_key_fun
); );
int avl_get_by_index ( int avl_get_by_index (
avl_tree * tree, avl_tree * tree,
unsigned long index, unsigned long index,
void ** value_address void ** value_address
); );
int avl_get_by_key ( int avl_get_by_key (
avl_tree * tree, avl_tree * tree,
void * key, void * key,
void ** value_address void ** value_address
); );
int avl_iterate_inorder ( int avl_iterate_inorder (
avl_tree * tree, avl_tree * tree,
avl_iter_fun_type iter_fun, avl_iter_fun_type iter_fun,
void * iter_arg void * iter_arg
); );
int avl_iterate_index_range ( int avl_iterate_index_range (
avl_tree * tree, avl_tree * tree,
avl_iter_index_fun_type iter_fun, avl_iter_index_fun_type iter_fun,
unsigned long low, unsigned long low,
unsigned long high, unsigned long high,
void * iter_arg void * iter_arg
); );
int avl_get_span_by_key ( int avl_get_span_by_key (
avl_tree * tree, avl_tree * tree,
void * key, void * key,
unsigned long * low, unsigned long * low,
unsigned long * high unsigned long * high
); );
int avl_get_span_by_two_keys ( int avl_get_span_by_two_keys (
avl_tree * tree, avl_tree * tree,
void * key_a, void * key_a,
void * key_b, void * key_b,
unsigned long * low, unsigned long * low,
unsigned long * high unsigned long * high
); );
int avl_verify (avl_tree * tree); int avl_verify (avl_tree * tree);
void avl_print_tree ( void avl_print_tree (
avl_tree * tree, avl_tree * tree,
avl_key_printer_fun_type key_printer avl_key_printer_fun_type key_printer
); );
@ -149,15 +149,15 @@ avl_node *avl_get_next(avl_node * node);
/* These two are from David Ascher <david_ascher@brown.edu> */ /* These two are from David Ascher <david_ascher@brown.edu> */
int avl_get_item_by_key_most ( int avl_get_item_by_key_most (
avl_tree * tree, avl_tree * tree,
void * key, void * key,
void ** value_address void ** value_address
); );
int avl_get_item_by_key_least ( int avl_get_item_by_key_least (
avl_tree * tree, avl_tree * tree,
void * key, void * key,
void ** value_address void ** value_address
); );
/* optional locking stuff */ /* optional locking stuff */

View File

@ -11,75 +11,75 @@ int _printer(char *buff, void *key);
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, max_nodes; int i, max_nodes;
avl_tree *tree; avl_tree *tree;
avl_node *node; avl_node *node;
max_nodes = 25; max_nodes = 25;
if (argc == 2) { if (argc == 2) {
max_nodes = atoi(argv[1]); max_nodes = atoi(argv[1]);
if (max_nodes == 0) if (max_nodes == 0)
max_nodes = 10; max_nodes = 10;
} }
printf("avl test... max_nodes = %d...\n", max_nodes); printf("avl test... max_nodes = %d...\n", max_nodes);
tree = avl_tree_new(_compare, NULL); tree = avl_tree_new(_compare, NULL);
printf("Filling tree...\n"); printf("Filling tree...\n");
for (i = 0; i < max_nodes; i++) { for (i = 0; i < max_nodes; i++) {
avl_insert(tree, (void *)rand()); avl_insert(tree, (void *)rand());
} }
printf("Traversing tree...\n"); printf("Traversing tree...\n");
node = avl_get_first(tree); node = avl_get_first(tree);
while (node) { while (node) {
i = (int)node->key; i = (int)node->key;
printf("...%5d\n", i); printf("...%5d\n", i);
node = avl_get_next(node); node = avl_get_next(node);
} }
printf("Trying to go backwards...\n"); printf("Trying to go backwards...\n");
node = tree->root->right; node = tree->root->right;
while (node) { while (node) {
i = (int)node->key; i = (int)node->key;
printf("...%5d\n", i); printf("...%5d\n", i);
node = avl_get_prev(node); node = avl_get_prev(node);
} }
printf("Printing tree...\n"); printf("Printing tree...\n");
avl_print_tree(tree, _printer); avl_print_tree(tree, _printer);
avl_tree_free(tree, _free); avl_tree_free(tree, _free);
return 0; return 0;
} }
int _compare(void *compare_arg, void *a, void *b) int _compare(void *compare_arg, void *a, void *b)
{ {
int i, j; int i, j;
i = (int)a; i = (int)a;
j = (int)b; j = (int)b;
if (i > j) if (i > j)
return 1; return 1;
if (j > i) if (j > i)
return -1; return -1;
return 0; return 0;
} }
int _free(void *key) int _free(void *key)
{ {
return 1; return 1;
} }
int _printer(char *buff, void *key) int _printer(char *buff, void *key)
{ {
return snprintf(buff, 25, "%d", (int)key); return snprintf(buff, 25, "%d", (int)key);
} }

View File

@ -33,50 +33,50 @@ int _free_vars(void *key);
http_parser_t *httpp_create_parser(void) http_parser_t *httpp_create_parser(void)
{ {
return (http_parser_t *)malloc(sizeof(http_parser_t)); return (http_parser_t *)malloc(sizeof(http_parser_t));
} }
void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults)
{ {
http_varlist_t *list; http_varlist_t *list;
parser->req_type = httpp_req_none; parser->req_type = httpp_req_none;
parser->uri = NULL; parser->uri = NULL;
parser->vars = avl_tree_new(_compare_vars, NULL); parser->vars = avl_tree_new(_compare_vars, NULL);
parser->queryvars = avl_tree_new(_compare_vars, NULL); parser->queryvars = avl_tree_new(_compare_vars, NULL);
/* now insert the default variables */ /* now insert the default variables */
list = defaults; list = defaults;
while (list != NULL) { while (list != NULL) {
httpp_setvar(parser, list->var.name, list->var.value); httpp_setvar(parser, list->var.name, list->var.value);
list = list->next; list = list->next;
} }
} }
static int split_headers(char *data, unsigned long len, char **line) static int split_headers(char *data, unsigned long len, char **line)
{ {
/* first we count how many lines there are /* first we count how many lines there are
** and set up the line[] array ** and set up the line[] array
*/ */
int lines = 0; int lines = 0;
unsigned long i; unsigned long i;
line[lines] = data; line[lines] = data;
for (i = 0; i < len && lines < MAX_HEADERS; i++) { for (i = 0; i < len && lines < MAX_HEADERS; i++) {
if (data[i] == '\r') if (data[i] == '\r')
data[i] = '\0'; data[i] = '\0';
if (data[i] == '\n') { if (data[i] == '\n') {
lines++; lines++;
data[i] = '\0'; data[i] = '\0';
if (i + 1 < len) { if (i + 1 < len) {
if (data[i + 1] == '\n' || data[i + 1] == '\r') if (data[i + 1] == '\n' || data[i + 1] == '\r')
break; break;
line[lines] = &data[i + 1]; line[lines] = &data[i + 1];
} }
} }
} }
i++; i++;
while (data[i] == '\n') i++; while (data[i] == '\n') i++;
return lines; return lines;
} }
@ -84,194 +84,194 @@ static int split_headers(char *data, unsigned long len, char **line)
static void parse_headers(http_parser_t *parser, char **line, int lines) static void parse_headers(http_parser_t *parser, char **line, int lines)
{ {
int i,l; int i,l;
int whitespace, where, slen; int whitespace, where, slen;
char *name = NULL; char *name = NULL;
char *value = NULL; char *value = NULL;
/* parse the name: value lines. */ /* parse the name: value lines. */
for (l = 1; l < lines; l++) { for (l = 1; l < lines; l++) {
where = 0; where = 0;
whitespace = 0; whitespace = 0;
name = line[l]; name = line[l];
value = NULL; value = NULL;
slen = strlen(line[l]); slen = strlen(line[l]);
for (i = 0; i < slen; i++) { for (i = 0; i < slen; i++) {
if (line[l][i] == ':') { if (line[l][i] == ':') {
whitespace = 1; whitespace = 1;
line[l][i] = '\0'; line[l][i] = '\0';
} else { } else {
if (whitespace) { if (whitespace) {
whitespace = 0; whitespace = 0;
while (i < slen && line[l][i] == ' ') while (i < slen && line[l][i] == ' ')
i++; i++;
if (i < slen) if (i < slen)
value = &line[l][i]; value = &line[l][i];
break; break;
} }
} }
} }
if (name != NULL && value != NULL) { if (name != NULL && value != NULL) {
httpp_setvar(parser, _lowercase(name), value); httpp_setvar(parser, _lowercase(name), value);
name = NULL; name = NULL;
value = NULL; value = NULL;
} }
} }
} }
int httpp_parse_response(http_parser_t *parser, char *http_data, unsigned long len, char *uri) int httpp_parse_response(http_parser_t *parser, char *http_data, unsigned long len, char *uri)
{ {
char *data; char *data;
char *line[MAX_HEADERS]; char *line[MAX_HEADERS];
int lines, slen,i, whitespace=0, where=0,code; int lines, slen,i, whitespace=0, where=0,code;
char *version=NULL, *resp_code=NULL, *message=NULL; char *version=NULL, *resp_code=NULL, *message=NULL;
if(http_data == NULL) if(http_data == NULL)
return 0; return 0;
/* make a local copy of the data, including 0 terminator */ /* make a local copy of the data, including 0 terminator */
data = (char *)malloc(len+1); data = (char *)malloc(len+1);
if (data == NULL) return 0; if (data == NULL) return 0;
memcpy(data, http_data, len); memcpy(data, http_data, len);
data[len] = 0; data[len] = 0;
lines = split_headers(data, len, line); lines = split_headers(data, len, line);
/* In this case, the first line contains: /* In this case, the first line contains:
* VERSION RESPONSE_CODE MESSAGE, such as HTTP/1.0 200 OK * VERSION RESPONSE_CODE MESSAGE, such as HTTP/1.0 200 OK
*/ */
slen = strlen(line[0]); slen = strlen(line[0]);
version = line[0]; version = line[0];
for(i=0; i < slen; i++) { for(i=0; i < slen; i++) {
if(line[0][i] == ' ') { if(line[0][i] == ' ') {
line[0][i] = 0; line[0][i] = 0;
whitespace = 1; whitespace = 1;
} else if(whitespace) { } else if(whitespace) {
whitespace = 0; whitespace = 0;
where++; where++;
if(where == 1) if(where == 1)
resp_code = &line[0][i]; resp_code = &line[0][i];
else { else {
message = &line[0][i]; message = &line[0][i];
break; break;
} }
} }
} }
if(version == NULL || resp_code == NULL || message == NULL) { if(version == NULL || resp_code == NULL || message == NULL) {
free(data); free(data);
return 0; return 0;
} }
httpp_setvar(parser, HTTPP_VAR_ERROR_CODE, resp_code); httpp_setvar(parser, HTTPP_VAR_ERROR_CODE, resp_code);
code = atoi(resp_code); code = atoi(resp_code);
if(code < 200 || code >= 300) { if(code < 200 || code >= 300) {
httpp_setvar(parser, HTTPP_VAR_ERROR_MESSAGE, message); httpp_setvar(parser, HTTPP_VAR_ERROR_MESSAGE, message);
} }
httpp_setvar(parser, HTTPP_VAR_URI, uri); httpp_setvar(parser, HTTPP_VAR_URI, uri);
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "NONE"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "NONE");
parse_headers(parser, line, lines); parse_headers(parser, line, lines);
free(data); free(data);
return 1; return 1;
} }
static int hex(char c) static int hex(char c)
{ {
if(c >= '0' && c <= '9') if(c >= '0' && c <= '9')
return c - '0'; return c - '0';
else if(c >= 'A' && c <= 'F') else if(c >= 'A' && c <= 'F')
return c - 'A' + 10; return c - 'A' + 10;
else if(c >= 'a' && c <= 'f') else if(c >= 'a' && c <= 'f')
return c - 'a' + 10; return c - 'a' + 10;
else else
return -1; return -1;
} }
static char *url_escape(char *src) static char *url_escape(char *src)
{ {
int len = strlen(src); int len = strlen(src);
unsigned char *decoded; unsigned char *decoded;
int i; int i;
char *dst; char *dst;
int done = 0; int done = 0;
decoded = calloc(1, len + 1); decoded = calloc(1, len + 1);
dst = decoded; dst = decoded;
for(i=0; i < len; i++) { for(i=0; i < len; i++) {
switch(src[i]) { switch(src[i]) {
case '%': case '%':
if(i+2 >= len) { if(i+2 >= len) {
free(decoded); free(decoded);
return NULL; return NULL;
} }
if(hex(src[i+1]) == -1 || hex(src[i+2]) == -1 ) { if(hex(src[i+1]) == -1 || hex(src[i+2]) == -1 ) {
free(decoded); free(decoded);
return NULL; return NULL;
} }
*dst++ = hex(src[i+1]) * 16 + hex(src[i+2]); *dst++ = hex(src[i+1]) * 16 + hex(src[i+2]);
i+= 2; i+= 2;
break; break;
case '#': case '#':
done = 1; done = 1;
break; break;
case 0: case 0:
free(decoded); free(decoded);
return NULL; return NULL;
break; break;
default: default:
*dst++ = src[i]; *dst++ = src[i];
break; break;
} }
if(done) if(done)
break; break;
} }
*dst = 0; /* null terminator */ *dst = 0; /* null terminator */
return decoded; return decoded;
} }
/** TODO: This is almost certainly buggy in some cases */ /** TODO: This is almost certainly buggy in some cases */
static void parse_query(http_parser_t *parser, char *query) static void parse_query(http_parser_t *parser, char *query)
{ {
int len; int len;
int i=0; int i=0;
char *key = query; char *key = query;
char *val=NULL; char *val=NULL;
if(!query || !*query) if(!query || !*query)
return; return;
len = strlen(query); len = strlen(query);
while(i<len) { while(i<len) {
switch(query[i]) { switch(query[i]) {
case '&': case '&':
query[i] = 0; query[i] = 0;
if(val && key) if(val && key)
httpp_set_query_param(parser, key, val); httpp_set_query_param(parser, key, val);
key = query+i+1; key = query+i+1;
break; break;
case '=': case '=':
query[i] = 0; query[i] = 0;
val = query+i+1; val = query+i+1;
break; break;
} }
i++; i++;
} }
if(val && key) { if(val && key) {
httpp_set_query_param(parser, key, val); httpp_set_query_param(parser, key, val);
} }
} }
/* The old shoutcast procotol. Don't look at this, it's really nasty */ /* The old shoutcast procotol. Don't look at this, it's really nasty */
@ -288,7 +288,7 @@ int httpp_parse_icy(http_parser_t *parser, char *http_data, unsigned long len)
memcpy(data, http_data, len); memcpy(data, http_data, len);
data[len] = 0; data[len] = 0;
lines = split_headers(data, len, line); lines = split_headers(data, len, line);
/* Now, this protocol looks like: /* Now, this protocol looks like:
* sourcepassword\n * sourcepassword\n
@ -313,261 +313,261 @@ int httpp_parse_icy(http_parser_t *parser, char *http_data, unsigned long len)
int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len) int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
{ {
char *data, *tmp; char *data, *tmp;
char *line[MAX_HEADERS]; /* limited to 32 lines, should be more than enough */ char *line[MAX_HEADERS]; /* limited to 32 lines, should be more than enough */
int i; int i;
int lines; int lines;
char *req_type = NULL; char *req_type = NULL;
char *uri = NULL; char *uri = NULL;
char *version = NULL; char *version = NULL;
int whitespace, where, slen; int whitespace, where, slen;
if (http_data == NULL) if (http_data == NULL)
return 0; return 0;
/* make a local copy of the data, including 0 terminator */ /* make a local copy of the data, including 0 terminator */
data = (char *)malloc(len+1); data = (char *)malloc(len+1);
if (data == NULL) return 0; if (data == NULL) return 0;
memcpy(data, http_data, len); memcpy(data, http_data, len);
data[len] = 0; data[len] = 0;
lines = split_headers(data, len, line); lines = split_headers(data, len, line);
/* parse the first line special /* parse the first line special
** the format is: ** the format is:
** REQ_TYPE URI VERSION ** REQ_TYPE URI VERSION
** eg: ** eg:
** GET /index.html HTTP/1.0 ** GET /index.html HTTP/1.0
*/ */
where = 0; where = 0;
whitespace = 0; whitespace = 0;
slen = strlen(line[0]); slen = strlen(line[0]);
req_type = line[0]; req_type = line[0];
for (i = 0; i < slen; i++) { for (i = 0; i < slen; i++) {
if (line[0][i] == ' ') { if (line[0][i] == ' ') {
whitespace = 1; whitespace = 1;
line[0][i] = '\0'; line[0][i] = '\0';
} else { } else {
/* we're just past the whitespace boundry */ /* we're just past the whitespace boundry */
if (whitespace) { if (whitespace) {
whitespace = 0; whitespace = 0;
where++; where++;
switch (where) { switch (where) {
case 1: case 1:
uri = &line[0][i]; uri = &line[0][i];
break; break;
case 2: case 2:
version = &line[0][i]; version = &line[0][i];
break; break;
} }
} }
} }
} }
if (strcasecmp("GET", req_type) == 0) { if (strcasecmp("GET", req_type) == 0) {
parser->req_type = httpp_req_get; parser->req_type = httpp_req_get;
} else if (strcasecmp("POST", req_type) == 0) { } else if (strcasecmp("POST", req_type) == 0) {
parser->req_type = httpp_req_post; parser->req_type = httpp_req_post;
} else if (strcasecmp("HEAD", req_type) == 0) { } else if (strcasecmp("HEAD", req_type) == 0) {
parser->req_type = httpp_req_head; parser->req_type = httpp_req_head;
} else if (strcasecmp("SOURCE", req_type) == 0) { } else if (strcasecmp("SOURCE", req_type) == 0) {
parser->req_type = httpp_req_source; parser->req_type = httpp_req_source;
} else if (strcasecmp("PLAY", req_type) == 0) { } else if (strcasecmp("PLAY", req_type) == 0) {
parser->req_type = httpp_req_play; parser->req_type = httpp_req_play;
} else if (strcasecmp("STATS", req_type) == 0) { } else if (strcasecmp("STATS", req_type) == 0) {
parser->req_type = httpp_req_stats; parser->req_type = httpp_req_stats;
} else { } else {
parser->req_type = httpp_req_unknown; parser->req_type = httpp_req_unknown;
} }
if (uri != NULL && strlen(uri) > 0) { if (uri != NULL && strlen(uri) > 0) {
char *query; char *query;
if((query = strchr(uri, '?')) != NULL) { if((query = strchr(uri, '?')) != NULL) {
*query = 0; *query = 0;
query++; query++;
parse_query(parser, query); parse_query(parser, query);
} }
parser->uri = strdup(uri); parser->uri = strdup(uri);
} else { } else {
free(data); free(data);
return 0; return 0;
} }
if ((version != NULL) && ((tmp = strchr(version, '/')) != NULL)) { if ((version != NULL) && ((tmp = strchr(version, '/')) != NULL)) {
tmp[0] = '\0'; tmp[0] = '\0';
if ((strlen(version) > 0) && (strlen(&tmp[1]) > 0)) { if ((strlen(version) > 0) && (strlen(&tmp[1]) > 0)) {
httpp_setvar(parser, HTTPP_VAR_PROTOCOL, version); httpp_setvar(parser, HTTPP_VAR_PROTOCOL, version);
httpp_setvar(parser, HTTPP_VAR_VERSION, &tmp[1]); httpp_setvar(parser, HTTPP_VAR_VERSION, &tmp[1]);
} else { } else {
free(data); free(data);
return 0; return 0;
} }
} else { } else {
free(data); free(data);
return 0; return 0;
} }
if (parser->req_type != httpp_req_none && parser->req_type != httpp_req_unknown) { if (parser->req_type != httpp_req_none && parser->req_type != httpp_req_unknown) {
switch (parser->req_type) { switch (parser->req_type) {
case httpp_req_get: case httpp_req_get:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "GET"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "GET");
break; break;
case httpp_req_post: case httpp_req_post:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "POST"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "POST");
break; break;
case httpp_req_head: case httpp_req_head:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "HEAD"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "HEAD");
break; break;
case httpp_req_source: case httpp_req_source:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "SOURCE"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "SOURCE");
break; break;
case httpp_req_play: case httpp_req_play:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "PLAY"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "PLAY");
break; break;
case httpp_req_stats: case httpp_req_stats:
httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "STATS"); httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "STATS");
break; break;
default: default:
break; break;
} }
} else { } else {
free(data); free(data);
return 0; return 0;
} }
if (parser->uri != NULL) { if (parser->uri != NULL) {
httpp_setvar(parser, HTTPP_VAR_URI, parser->uri); httpp_setvar(parser, HTTPP_VAR_URI, parser->uri);
} else { } else {
free(data); free(data);
return 0; return 0;
} }
parse_headers(parser, line, lines); parse_headers(parser, line, lines);
free(data); free(data);
return 1; return 1;
} }
void httpp_setvar(http_parser_t *parser, char *name, char *value) void httpp_setvar(http_parser_t *parser, char *name, char *value)
{ {
http_var_t *var; http_var_t *var;
if (name == NULL || value == NULL) if (name == NULL || value == NULL)
return; return;
var = (http_var_t *)malloc(sizeof(http_var_t)); var = (http_var_t *)malloc(sizeof(http_var_t));
if (var == NULL) return; if (var == NULL) return;
var->name = strdup(name); var->name = strdup(name);
var->value = strdup(value); var->value = strdup(value);
if (httpp_getvar(parser, name) == NULL) { if (httpp_getvar(parser, name) == NULL) {
avl_insert(parser->vars, (void *)var); avl_insert(parser->vars, (void *)var);
} else { } else {
avl_delete(parser->vars, (void *)var, _free_vars); avl_delete(parser->vars, (void *)var, _free_vars);
avl_insert(parser->vars, (void *)var); avl_insert(parser->vars, (void *)var);
} }
} }
char *httpp_getvar(http_parser_t *parser, char *name) char *httpp_getvar(http_parser_t *parser, char *name)
{ {
http_var_t var; http_var_t var;
http_var_t *found; http_var_t *found;
var.name = name; var.name = name;
var.value = NULL; var.value = NULL;
if (avl_get_by_key(parser->vars, (void *)&var, (void **)&found) == 0) if (avl_get_by_key(parser->vars, (void *)&var, (void **)&found) == 0)
return found->value; return found->value;
else else
return NULL; return NULL;
} }
void httpp_set_query_param(http_parser_t *parser, char *name, char *value) void httpp_set_query_param(http_parser_t *parser, char *name, char *value)
{ {
http_var_t *var; http_var_t *var;
if (name == NULL || value == NULL) if (name == NULL || value == NULL)
return; return;
var = (http_var_t *)malloc(sizeof(http_var_t)); var = (http_var_t *)malloc(sizeof(http_var_t));
if (var == NULL) return; if (var == NULL) return;
var->name = strdup(name); var->name = strdup(name);
var->value = url_escape(value); var->value = url_escape(value);
if (httpp_get_query_param(parser, name) == NULL) { if (httpp_get_query_param(parser, name) == NULL) {
avl_insert(parser->queryvars, (void *)var); avl_insert(parser->queryvars, (void *)var);
} else { } else {
avl_delete(parser->queryvars, (void *)var, _free_vars); avl_delete(parser->queryvars, (void *)var, _free_vars);
avl_insert(parser->queryvars, (void *)var); avl_insert(parser->queryvars, (void *)var);
} }
} }
char *httpp_get_query_param(http_parser_t *parser, char *name) char *httpp_get_query_param(http_parser_t *parser, char *name)
{ {
http_var_t var; http_var_t var;
http_var_t *found; http_var_t *found;
var.name = name; var.name = name;
var.value = NULL; var.value = NULL;
if (avl_get_by_key(parser->queryvars, (void *)&var, (void **)&found) == 0) if (avl_get_by_key(parser->queryvars, (void *)&var, (void **)&found) == 0)
return found->value; return found->value;
else else
return NULL; return NULL;
} }
void httpp_clear(http_parser_t *parser) void httpp_clear(http_parser_t *parser)
{ {
parser->req_type = httpp_req_none; parser->req_type = httpp_req_none;
if (parser->uri) if (parser->uri)
free(parser->uri); free(parser->uri);
parser->uri = NULL; parser->uri = NULL;
avl_tree_free(parser->vars, _free_vars); avl_tree_free(parser->vars, _free_vars);
avl_tree_free(parser->queryvars, _free_vars); avl_tree_free(parser->queryvars, _free_vars);
parser->vars = NULL; parser->vars = NULL;
} }
void httpp_destroy(http_parser_t *parser) void httpp_destroy(http_parser_t *parser)
{ {
httpp_clear(parser); httpp_clear(parser);
free(parser); free(parser);
} }
char *_lowercase(char *str) char *_lowercase(char *str)
{ {
long i; long i;
for (i = 0; i < strlen(str); i++) for (i = 0; i < strlen(str); i++)
str[i] = tolower(str[i]); str[i] = tolower(str[i]);
return str; return str;
} }
int _compare_vars(void *compare_arg, void *a, void *b) int _compare_vars(void *compare_arg, void *a, void *b)
{ {
http_var_t *vara, *varb; http_var_t *vara, *varb;
vara = (http_var_t *)a; vara = (http_var_t *)a;
varb = (http_var_t *)b; varb = (http_var_t *)b;
return strcmp(vara->name, varb->name); return strcmp(vara->name, varb->name);
} }
int _free_vars(void *key) int _free_vars(void *key)
{ {
http_var_t *var; http_var_t *var;
var = (http_var_t *)key; var = (http_var_t *)key;
if (var->name) if (var->name)
free(var->name); free(var->name);
if (var->value) if (var->value)
free(var->value); free(var->value);
free(var); free(var);
return 1; return 1;
} }

View File

@ -17,25 +17,25 @@
#define HTTPP_VAR_ICYPASSWORD "__icy_password" #define HTTPP_VAR_ICYPASSWORD "__icy_password"
typedef enum httpp_request_type_tag { typedef enum httpp_request_type_tag {
httpp_req_none, httpp_req_get, httpp_req_post, httpp_req_head, httpp_req_none, httpp_req_get, httpp_req_post, httpp_req_head,
httpp_req_source, httpp_req_play, httpp_req_stats, httpp_req_unknown httpp_req_source, httpp_req_play, httpp_req_stats, httpp_req_unknown
} httpp_request_type_e; } httpp_request_type_e;
typedef struct http_var_tag { typedef struct http_var_tag {
char *name; char *name;
char *value; char *value;
} http_var_t; } http_var_t;
typedef struct http_varlist_tag { typedef struct http_varlist_tag {
http_var_t var; http_var_t var;
struct http_varlist_tag *next; struct http_varlist_tag *next;
} http_varlist_t; } http_varlist_t;
typedef struct http_parser_tag { typedef struct http_parser_tag {
httpp_request_type_e req_type; httpp_request_type_e req_type;
char *uri; char *uri;
avl_tree *vars; avl_tree *vars;
avl_tree *queryvars; avl_tree *queryvars;
} http_parser_t; } http_parser_t;
http_parser_t *httpp_create_parser(void); http_parser_t *httpp_create_parser(void);

View File

@ -6,54 +6,54 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buff[8192]; char buff[8192];
int readed; int readed;
http_parser_t parser; http_parser_t parser;
avl_node *node; avl_node *node;
http_var_t *var; http_var_t *var;
httpp_initialize(&parser, NULL); httpp_initialize(&parser, NULL);
readed = fread(buff, 1, 8192, stdin); readed = fread(buff, 1, 8192, stdin);
if (httpp_parse(&parser, buff, readed)) { if (httpp_parse(&parser, buff, readed)) {
printf("Parse succeeded...\n\n"); printf("Parse succeeded...\n\n");
printf("Request was "); printf("Request was ");
switch (parser.req_type) { switch (parser.req_type) {
case httpp_req_none: case httpp_req_none:
printf(" none\n"); printf(" none\n");
break; break;
case httpp_req_unknown: case httpp_req_unknown:
printf(" unknown\n"); printf(" unknown\n");
break; break;
case httpp_req_get: case httpp_req_get:
printf(" get\n"); printf(" get\n");
break; break;
case httpp_req_post: case httpp_req_post:
printf(" post\n"); printf(" post\n");
break; break;
case httpp_req_head: case httpp_req_head:
printf(" head\n"); printf(" head\n");
break; break;
} }
printf("Version was 1.%d\n", parser.version); printf("Version was 1.%d\n", parser.version);
node = avl_get_first(parser.vars); node = avl_get_first(parser.vars);
while (node) { while (node) {
var = (http_var_t *)node->key; var = (http_var_t *)node->key;
if (var) if (var)
printf("Iterating variable(s): %s = %s\n", var->name, var->value); printf("Iterating variable(s): %s = %s\n", var->name, var->value);
node = avl_get_next(node); node = avl_get_next(node);
} }
} else { } else {
printf("Parse failed...\n"); printf("Parse failed...\n");
} }
printf("Destroying parser...\n"); printf("Destroying parser...\n");
httpp_destroy(&parser); httpp_destroy(&parser);
return 0; return 0;
} }

198
log/log.c
View File

@ -28,13 +28,13 @@ static int _initialized = 0;
typedef struct log_tag typedef struct log_tag
{ {
int in_use; int in_use;
int level; int level;
char *filename; char *filename;
FILE *logfile; FILE *logfile;
char *buffer; char *buffer;
} log_t; } log_t;
@ -47,26 +47,26 @@ static void _unlock_logger();
void log_initialize() void log_initialize()
{ {
int i; int i;
if (_initialized) return; if (_initialized) return;
for (i = 0; i < LOG_MAXLOGS; i++) { for (i = 0; i < LOG_MAXLOGS; i++) {
loglist[i].in_use = 0; loglist[i].in_use = 0;
loglist[i].level = 2; loglist[i].level = 2;
loglist[i].filename = NULL; loglist[i].filename = NULL;
loglist[i].logfile = NULL; loglist[i].logfile = NULL;
loglist[i].buffer = NULL; loglist[i].buffer = NULL;
} }
/* initialize mutexes */ /* initialize mutexes */
#ifndef _WIN32 #ifndef _WIN32
pthread_mutex_init(&_logger_mutex, NULL); pthread_mutex_init(&_logger_mutex, NULL);
#else #else
InitializeCriticalSection(&_logger_mutex); InitializeCriticalSection(&_logger_mutex);
#endif #endif
_initialized = 1; _initialized = 1;
} }
int log_open_file(FILE *file) int log_open_file(FILE *file)
@ -75,34 +75,34 @@ int log_open_file(FILE *file)
if(file == NULL) return LOG_EINSANE; if(file == NULL) return LOG_EINSANE;
log_id = _get_log_id(); log_id = _get_log_id();
if (log_id < 0) return LOG_ENOMORELOGS; if (log_id < 0) return LOG_ENOMORELOGS;
loglist[log_id].logfile = file; loglist[log_id].logfile = file;
if (loglist[log_id].logfile != NULL) { if (loglist[log_id].logfile != NULL) {
loglist[log_id].filename = NULL; loglist[log_id].filename = NULL;
} else { } else {
_release_log_id(log_id); _release_log_id(log_id);
return LOG_ECANTOPEN; return LOG_ECANTOPEN;
} }
return log_id; return log_id;
} }
int log_open(const char *filename) int log_open(const char *filename)
{ {
int ret; int ret;
FILE *file; FILE *file;
if (filename == NULL) return LOG_EINSANE; if (filename == NULL) return LOG_EINSANE;
if (strcmp(filename, "") == 0) return LOG_EINSANE; if (strcmp(filename, "") == 0) return LOG_EINSANE;
file = fopen(filename, "a"); file = fopen(filename, "a");
ret = log_open_file(file); ret = log_open_file(file);
if(ret >= 0) if(ret >= 0)
setvbuf(file, NULL, IO_BUFFER_TYPE, 0); setvbuf(file, NULL, IO_BUFFER_TYPE, 0);
return ret; return ret;
@ -110,152 +110,152 @@ int log_open(const char *filename)
int log_open_with_buffer(const char *filename, int size) int log_open_with_buffer(const char *filename, int size)
{ {
/* not implemented */ /* not implemented */
return LOG_ENOTIMPL; return LOG_ENOTIMPL;
} }
void log_set_level(int log_id, int level) void log_set_level(int log_id, int level)
{ {
if (log_id < 0 || log_id >= LOG_MAXLOGS) return; if (log_id < 0 || log_id >= LOG_MAXLOGS) return;
if (loglist[log_id].in_use == 0) return; if (loglist[log_id].in_use == 0) return;
loglist[log_id].level = level; loglist[log_id].level = level;
} }
void log_flush(int log_id) void log_flush(int log_id)
{ {
if (log_id < 0 || log_id >= LOG_MAXLOGS) return; if (log_id < 0 || log_id >= LOG_MAXLOGS) return;
if (loglist[log_id].in_use == 0) return; if (loglist[log_id].in_use == 0) return;
fflush(loglist[log_id].logfile); fflush(loglist[log_id].logfile);
} }
void log_reopen(int log_id) void log_reopen(int log_id)
{ {
/* not implemented yet */ /* not implemented yet */
} }
void log_close(int log_id) void log_close(int log_id)
{ {
if (log_id < 0 || log_id >= LOG_MAXLOGS) return; if (log_id < 0 || log_id >= LOG_MAXLOGS) return;
if (loglist[log_id].in_use == 0) return; if (loglist[log_id].in_use == 0) return;
loglist[log_id].in_use = 0; loglist[log_id].in_use = 0;
loglist[log_id].level = 2; loglist[log_id].level = 2;
if (loglist[log_id].filename) free(loglist[log_id].filename); if (loglist[log_id].filename) free(loglist[log_id].filename);
if (loglist[log_id].buffer) free(loglist[log_id].buffer); if (loglist[log_id].buffer) free(loglist[log_id].buffer);
fclose(loglist[log_id].logfile); fclose(loglist[log_id].logfile);
loglist[log_id].logfile = NULL; loglist[log_id].logfile = NULL;
} }
void log_shutdown() void log_shutdown()
{ {
/* destroy mutexes */ /* destroy mutexes */
#ifndef _WIN32 #ifndef _WIN32
pthread_mutex_destroy(&_logger_mutex); pthread_mutex_destroy(&_logger_mutex);
#else #else
DeleteCriticalSection(&_logger_mutex); DeleteCriticalSection(&_logger_mutex);
#endif #endif
_initialized = 0; _initialized = 0;
} }
void log_write(int log_id, int priority, const char *cat, const char *func, void log_write(int log_id, int priority, const char *cat, const char *func,
const char *fmt, ...) const char *fmt, ...)
{ {
static char prior[4][5] = { "EROR\0", "WARN\0", "INFO\0", "DBUG\0" }; static char prior[4][5] = { "EROR\0", "WARN\0", "INFO\0", "DBUG\0" };
char tyme[128]; char tyme[128];
char pre[256]; char pre[256];
char line[LOG_MAXLINELEN]; char line[LOG_MAXLINELEN];
time_t now; time_t now;
va_list ap; va_list ap;
if (log_id < 0) return; if (log_id < 0) return;
if (log_id > LOG_MAXLOGS) return; /* Bad log number */ if (log_id > LOG_MAXLOGS) return; /* Bad log number */
if (loglist[log_id].level < priority) return; if (loglist[log_id].level < priority) return;
if (priority > 4) return; /* Bad priority */ if (priority > 4) return; /* Bad priority */
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(line, LOG_MAXLINELEN, fmt, ap); vsnprintf(line, LOG_MAXLINELEN, fmt, ap);
now = time(NULL); now = time(NULL);
/* localtime() isn't threadsafe, localtime_r isn't portable enough... */ /* localtime() isn't threadsafe, localtime_r isn't portable enough... */
_lock_logger(); _lock_logger();
strftime(tyme, 128, "[%Y-%m-%d %H:%M:%S]", localtime(&now)); strftime(tyme, 128, "[%Y-%m-%d %H:%M:%S]", localtime(&now));
_unlock_logger(); _unlock_logger();
snprintf(pre, 256, "%s %s%s", prior[priority-1], cat, func); snprintf(pre, 256, "%s %s%s", prior[priority-1], cat, func);
fprintf(loglist[log_id].logfile, "%s %s %s\n", tyme, pre, line); fprintf(loglist[log_id].logfile, "%s %s %s\n", tyme, pre, line);
va_end(ap); va_end(ap);
} }
void log_write_direct(int log_id, const char *fmt, ...) void log_write_direct(int log_id, const char *fmt, ...)
{ {
char line[LOG_MAXLINELEN]; char line[LOG_MAXLINELEN];
va_list ap; va_list ap;
if (log_id < 0) return; if (log_id < 0) return;
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(line, LOG_MAXLINELEN, fmt, ap); vsnprintf(line, LOG_MAXLINELEN, fmt, ap);
fprintf(loglist[log_id].logfile, "%s\n", line); fprintf(loglist[log_id].logfile, "%s\n", line);
va_end(ap); va_end(ap);
fflush(loglist[log_id].logfile); fflush(loglist[log_id].logfile);
} }
int _get_log_id() int _get_log_id()
{ {
int i; int i;
int id = -1; int id = -1;
/* lock mutex */ /* lock mutex */
_lock_logger(); _lock_logger();
for (i = 0; i < LOG_MAXLOGS; i++) for (i = 0; i < LOG_MAXLOGS; i++)
if (loglist[i].in_use == 0) { if (loglist[i].in_use == 0) {
loglist[i].in_use = 1; loglist[i].in_use = 1;
id = i; id = i;
break; break;
} }
/* unlock mutex */ /* unlock mutex */
_unlock_logger(); _unlock_logger();
return id; return id;
} }
void _release_log_id(int log_id) void _release_log_id(int log_id)
{ {
/* lock mutex */ /* lock mutex */
_lock_logger(); _lock_logger();
loglist[log_id].in_use = 0; loglist[log_id].in_use = 0;
/* unlock mutex */ /* unlock mutex */
_unlock_logger(); _unlock_logger();
} }
static void _lock_logger() static void _lock_logger()
{ {
#ifndef _WIN32 #ifndef _WIN32
pthread_mutex_lock(&_logger_mutex); pthread_mutex_lock(&_logger_mutex);
#else #else
EnterCriticalSection(&_logger_mutex); EnterCriticalSection(&_logger_mutex);
#endif #endif
} }
static void _unlock_logger() static void _unlock_logger()
{ {
#ifndef _WIN32 #ifndef _WIN32
pthread_mutex_unlock(&_logger_mutex); pthread_mutex_unlock(&_logger_mutex);
#else #else
LeaveCriticalSection(&_logger_mutex); LeaveCriticalSection(&_logger_mutex);
#endif #endif
} }

View File

@ -7,15 +7,15 @@
int main(void) int main(void)
{ {
int lid; int lid;
log_initialize(); log_initialize();
lid = log_open("test.log"); lid = log_open("test.log");
LOG_ERR(lid, "The log id is %d, damnit...", lid); LOG_ERR(lid, "The log id is %d, damnit...", lid);
log_close(lid); log_close(lid);
log_shutdown(); log_shutdown();
} }

View File

@ -47,7 +47,7 @@
#define ENOTSOCK WSAENOTSOCK #define ENOTSOCK WSAENOTSOCK
#define EWOULDBLOCK WSAEWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK
#define EALREADY WSAEALREADY #define EALREADY WSAEALREADY
#define socklen_t int #define socklen_t int
#endif #endif
#include "sock.h" #include "sock.h"
@ -61,11 +61,11 @@
void sock_initialize(void) void sock_initialize(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsad; WSADATA wsad;
WSAStartup(0x0101, &wsad); WSAStartup(0x0101, &wsad);
#endif #endif
resolver_initialize(); resolver_initialize();
} }
/* sock_shutdown /* sock_shutdown
@ -76,7 +76,7 @@ void sock_initialize(void)
void sock_shutdown(void) void sock_shutdown(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
WSACleanup(); WSACleanup();
#endif #endif
} }
@ -89,15 +89,15 @@ void sock_shutdown(void)
*/ */
char *sock_get_localip(char *buff, int len) char *sock_get_localip(char *buff, int len)
{ {
char temp[1024]; char temp[1024];
if (gethostname(temp, 1024) != 0) if (gethostname(temp, 1024) != 0)
return NULL; return NULL;
if (resolver_getip(temp, buff, len)) if (resolver_getip(temp, buff, len))
return buff; return buff;
return NULL; return NULL;
} }
/* sock_error /* sock_error
@ -107,9 +107,9 @@ char *sock_get_localip(char *buff, int len)
int sock_error(void) int sock_error(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
return WSAGetLastError(); return WSAGetLastError();
#else #else
return errno; return errno;
#endif #endif
} }
@ -163,15 +163,15 @@ int sock_valid_socket(sock_t sock)
#ifdef _WIN32 #ifdef _WIN32
int inet_aton(const char *s, struct in_addr *a) int inet_aton(const char *s, struct in_addr *a)
{ {
int lsb, b2, b3, msb; int lsb, b2, b3, msb;
if (sscanf(s, "%d.%d.%d.%d", &lsb, &b2, &b3, &msb) < 4) { if (sscanf(s, "%d.%d.%d.%d", &lsb, &b2, &b3, &msb) < 4) {
return 0; return 0;
} }
a->s_addr = inet_addr(s); a->s_addr = inet_addr(s);
return (a->s_addr != INADDR_NONE); return (a->s_addr != INADDR_NONE);
} }
#endif /* _WIN32 */ #endif /* _WIN32 */
@ -184,23 +184,23 @@ int inet_aton(const char *s, struct in_addr *a)
int sock_set_blocking(sock_t sock, const int block) int sock_set_blocking(sock_t sock, const int block)
{ {
#ifdef _WIN32 #ifdef _WIN32
int varblock = block; int varblock = block;
#endif #endif
if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1)) if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1))
return SOCK_ERROR; return SOCK_ERROR;
#ifdef _WIN32 #ifdef _WIN32
return ioctlsocket(sock, FIONBIO, &varblock); return ioctlsocket(sock, FIONBIO, &varblock);
#else #else
return fcntl(sock, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK); return fcntl(sock, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK);
#endif #endif
} }
int sock_set_nolinger(sock_t sock) int sock_set_nolinger(sock_t sock)
{ {
struct linger lin = { 0, 0 }; struct linger lin = { 0, 0 };
return setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&lin, return setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&lin,
sizeof(struct linger)); sizeof(struct linger));
} }
@ -214,8 +214,8 @@ int sock_set_nodelay(sock_t sock)
int sock_set_keepalive(sock_t sock) int sock_set_keepalive(sock_t sock)
{ {
int keepalive = 1; int keepalive = 1;
return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,
sizeof(int)); sizeof(int));
} }
@ -226,9 +226,9 @@ int sock_set_keepalive(sock_t sock)
int sock_close(sock_t sock) int sock_close(sock_t sock)
{ {
#ifdef _WIN32 #ifdef _WIN32
return closesocket(sock); return closesocket(sock);
#else #else
return close(sock); return close(sock);
#endif #endif
} }
@ -278,16 +278,16 @@ ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count)
*/ */
int sock_write_bytes(sock_t sock, const void *buff, const size_t len) int sock_write_bytes(sock_t sock, const void *buff, const size_t len)
{ {
/* sanity check */ /* sanity check */
if (!buff) { if (!buff) {
return SOCK_ERROR; return SOCK_ERROR;
} else if (len <= 0) { } else if (len <= 0) {
return SOCK_ERROR; return SOCK_ERROR;
} /*else if (!sock_valid_socket(sock)) { } /*else if (!sock_valid_socket(sock)) {
return SOCK_ERROR; return SOCK_ERROR;
} */ } */
return send(sock, buff, len, 0); return send(sock, buff, len, 0);
} }
/* sock_write_string /* sock_write_string
@ -297,7 +297,7 @@ int sock_write_bytes(sock_t sock, const void *buff, const size_t len)
*/ */
int sock_write_string(sock_t sock, const char *buff) int sock_write_string(sock_t sock, const char *buff)
{ {
return (sock_write_bytes(sock, buff, strlen(buff)) > 0); return (sock_write_bytes(sock, buff, strlen(buff)) > 0);
} }
/* sock_write /* sock_write
@ -308,14 +308,14 @@ int sock_write_string(sock_t sock, const char *buff)
*/ */
int sock_write(sock_t sock, const char *fmt, ...) int sock_write(sock_t sock, const char *fmt, ...)
{ {
char buff[1024]; char buff[1024];
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(buff, 1024, fmt, ap); vsnprintf(buff, 1024, fmt, ap);
va_end(ap); va_end(ap);
return sock_write_bytes(sock, buff, strlen(buff)); return sock_write_bytes(sock, buff, strlen(buff));
} }
int sock_write_fmt(sock_t sock, char *fmt, va_list ap) int sock_write_fmt(sock_t sock, char *fmt, va_list ap)
@ -330,11 +330,11 @@ int sock_write_fmt(sock_t sock, char *fmt, va_list ap)
int sock_read_bytes(sock_t sock, char *buff, const int len) int sock_read_bytes(sock_t sock, char *buff, const int len)
{ {
/*if (!sock_valid_socket(sock)) return 0; */ /*if (!sock_valid_socket(sock)) return 0; */
if (!buff) return 0; if (!buff) return 0;
if (len <= 0) return 0; if (len <= 0) return 0;
return recv(sock, buff, len, 0); return recv(sock, buff, len, 0);
} }
/* sock_read_line /* sock_read_line
@ -347,36 +347,36 @@ int sock_read_bytes(sock_t sock, char *buff, const int len)
*/ */
int sock_read_line(sock_t sock, char *buff, const int len) int sock_read_line(sock_t sock, char *buff, const int len)
{ {
char c = '\0'; char c = '\0';
int read_bytes, pos; int read_bytes, pos;
/*if (!sock_valid_socket(sock)) { /*if (!sock_valid_socket(sock)) {
return 0; return 0;
} else*/ if (!buff) { } else*/ if (!buff) {
return 0; return 0;
} else if (len <= 0) { } else if (len <= 0) {
return 0; return 0;
} }
pos = 0; pos = 0;
read_bytes = recv(sock, &c, 1, 0); read_bytes = recv(sock, &c, 1, 0);
if (read_bytes < 0) { if (read_bytes < 0) {
return 0; return 0;
} }
while ((c != '\n') && (pos < len) && (read_bytes == 1)) { while ((c != '\n') && (pos < len) && (read_bytes == 1)) {
if (c != '\r') if (c != '\r')
buff[pos++] = c; buff[pos++] = c;
read_bytes = recv(sock, &c, 1, 0); read_bytes = recv(sock, &c, 1, 0);
} }
if (read_bytes == 1) { if (read_bytes == 1) {
buff[pos] = '\0'; buff[pos] = '\0';
return 1; return 1;
} else { } else {
return 0; return 0;
} }
} }
/* see if a connection can be written to /* see if a connection can be written to
@ -588,99 +588,99 @@ sock_t sock_connect_wto(const char *hostname, const int port, const int timeout)
sock_t sock_get_server_socket(const int port, char *sinterface) sock_t sock_get_server_socket(const int port, char *sinterface)
{ {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct sockaddr_storage sa; struct sockaddr_storage sa;
#else #else
struct sockaddr_in sa; struct sockaddr_in sa;
#endif #endif
int sa_family, sa_len, error, opt; int sa_family, sa_len, error, opt;
sock_t sock; sock_t sock;
char ip[MAX_ADDR_LEN]; char ip[MAX_ADDR_LEN];
if (port < 0) if (port < 0)
return SOCK_ERROR; return SOCK_ERROR;
/* defaults */ /* defaults */
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa_family = AF_INET; sa_family = AF_INET;
sa_len = sizeof(struct sockaddr_in); sa_len = sizeof(struct sockaddr_in);
/* set the interface to bind to if specified */ /* set the interface to bind to if specified */
if (sinterface != NULL) { if (sinterface != NULL) {
if (!resolver_getip(sinterface, ip, sizeof (ip))) if (!resolver_getip(sinterface, ip, sizeof (ip)))
return SOCK_ERROR; return SOCK_ERROR;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (inet_pton(AF_INET, ip, &((struct sockaddr_in*)&sa)->sin_addr) > 0) { if (inet_pton(AF_INET, ip, &((struct sockaddr_in*)&sa)->sin_addr) > 0) {
((struct sockaddr_in*)&sa)->sin_family = AF_INET; ((struct sockaddr_in*)&sa)->sin_family = AF_INET;
((struct sockaddr_in*)&sa)->sin_port = htons(port); ((struct sockaddr_in*)&sa)->sin_port = htons(port);
} else if (inet_pton(AF_INET6, ip, } else if (inet_pton(AF_INET6, ip,
&((struct sockaddr_in6*)&sa)->sin6_addr) > 0) { &((struct sockaddr_in6*)&sa)->sin6_addr) > 0) {
sa_family = AF_INET6; sa_family = AF_INET6;
sa_len = sizeof (struct sockaddr_in6); sa_len = sizeof (struct sockaddr_in6);
((struct sockaddr_in6*)&sa)->sin6_family = AF_INET6; ((struct sockaddr_in6*)&sa)->sin6_family = AF_INET6;
((struct sockaddr_in6*)&sa)->sin6_port = htons(port); ((struct sockaddr_in6*)&sa)->sin6_port = htons(port);
} else { } else {
return SOCK_ERROR; return SOCK_ERROR;
} }
#else #else
if (!inet_aton(ip, &sa.sin_addr)) { if (!inet_aton(ip, &sa.sin_addr)) {
return SOCK_ERROR; return SOCK_ERROR;
} else { } else {
sa.sin_family = AF_INET; sa.sin_family = AF_INET;
sa.sin_port = htons(port); sa.sin_port = htons(port);
} }
#endif #endif
} else { } else {
((struct sockaddr_in*)&sa)->sin_addr.s_addr = INADDR_ANY; ((struct sockaddr_in*)&sa)->sin_addr.s_addr = INADDR_ANY;
((struct sockaddr_in*)&sa)->sin_family = AF_INET; ((struct sockaddr_in*)&sa)->sin_family = AF_INET;
((struct sockaddr_in*)&sa)->sin_port = htons(port); ((struct sockaddr_in*)&sa)->sin_port = htons(port);
} }
/* get a socket */ /* get a socket */
sock = socket(sa_family, SOCK_STREAM, 0); sock = socket(sa_family, SOCK_STREAM, 0);
if (sock == -1) if (sock == -1)
return SOCK_ERROR; return SOCK_ERROR;
/* reuse it if we can */ /* reuse it if we can */
opt = 1; opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int)); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int));
/* bind socket to port */ /* bind socket to port */
error = bind(sock, (struct sockaddr *)&sa, sa_len); error = bind(sock, (struct sockaddr *)&sa, sa_len);
if (error == -1) if (error == -1)
return SOCK_ERROR; return SOCK_ERROR;
return sock; return sock;
} }
int sock_listen(sock_t serversock, int backlog) int sock_listen(sock_t serversock, int backlog)
{ {
if (!sock_valid_socket(serversock)) if (!sock_valid_socket(serversock))
return 0; return 0;
if (backlog <= 0) if (backlog <= 0)
backlog = 10; backlog = 10;
return (listen(serversock, backlog) == 0); return (listen(serversock, backlog) == 0);
} }
int sock_accept(sock_t serversock, char *ip, int len) int sock_accept(sock_t serversock, char *ip, int len)
{ {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct sockaddr_storage sa; struct sockaddr_storage sa;
#else #else
struct sockaddr_in sa; struct sockaddr_in sa;
#endif #endif
int ret; int ret;
socklen_t slen; socklen_t slen;
if (!sock_valid_socket(serversock)) if (!sock_valid_socket(serversock))
return SOCK_ERROR; return SOCK_ERROR;
slen = sizeof(sa); slen = sizeof(sa);
ret = accept(serversock, (struct sockaddr *)&sa, &slen); ret = accept(serversock, (struct sockaddr *)&sa, &slen);
if (ret >= 0 && ip != NULL) { if (ret >= 0 && ip != NULL) {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if(((struct sockaddr_in *)&sa)->sin_family == AF_INET) if(((struct sockaddr_in *)&sa)->sin_family == AF_INET)
inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr, inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr,
@ -694,12 +694,12 @@ int sock_accept(sock_t serversock, char *ip, int len)
} }
#else #else
/* inet_ntoa is not reentrant, we should protect this */ /* inet_ntoa is not reentrant, we should protect this */
strncpy(ip, inet_ntoa(sa.sin_addr), len); strncpy(ip, inet_ntoa(sa.sin_addr), len);
#endif #endif
sock_set_nolinger(ret); sock_set_nolinger(ret);
sock_set_keepalive(ret); sock_set_keepalive(ret);
} }
return ret; return ret;
} }

View File

@ -5,13 +5,13 @@
int main() int main()
{ {
char buff[1024]; char buff[1024];
resolver_initialize(); resolver_initialize();
printf("I got %s, when looking up %s.\n", resolver_getip("bach.greenwitch.com", buff, 1024), "bach.greenwitch.com"); printf("I got %s, when looking up %s.\n", resolver_getip("bach.greenwitch.com", buff, 1024), "bach.greenwitch.com");
printf("I got %s, when looking up %s.\n", resolver_getname("207.181.249.14", buff, 1024), "207.181.249.14"); printf("I got %s, when looking up %s.\n", resolver_getname("207.181.249.14", buff, 1024), "207.181.249.14");
return 0; return 0;
} }

View File

@ -74,18 +74,18 @@
/* thread starting structure */ /* thread starting structure */
typedef struct thread_start_tag { typedef struct thread_start_tag {
/* the real start routine and arg */ /* the real start routine and arg */
void *(*start_routine)(void *); void *(*start_routine)(void *);
void *arg; void *arg;
/* whether to create the threaded in detached state */ /* whether to create the threaded in detached state */
int detached; int detached;
/* the other stuff we need to make sure this thread is inserted into /* the other stuff we need to make sure this thread is inserted into
** the thread tree ** the thread tree
*/ */
thread_type *thread; thread_type *thread;
pthread_t sys_thread; pthread_t sys_thread;
} thread_start_t; } thread_start_t;
static long _next_thread_id = 0; static long _next_thread_id = 0;
@ -143,69 +143,69 @@ static void _block_signals(void);
void thread_initialize(void) void thread_initialize(void)
{ {
thread_type *thread; thread_type *thread;
/* set up logging */ /* set up logging */
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
log_initialize(); log_initialize();
_logid = log_open("thread.log"); _logid = log_open("thread.log");
log_set_level(_logid, THREAD_DEBUG); log_set_level(_logid, THREAD_DEBUG);
#endif #endif
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
/* create all the internal mutexes, and initialize the mutex tree */ /* create all the internal mutexes, and initialize the mutex tree */
_mutextree = avl_tree_new(_compare_mutexes, NULL); _mutextree = avl_tree_new(_compare_mutexes, NULL);
/* we have to create this one by hand, because there's no /* we have to create this one by hand, because there's no
** mutextree_mutex to lock yet! ** mutextree_mutex to lock yet!
*/ */
_mutex_create(&_mutextree_mutex); _mutex_create(&_mutextree_mutex);
_mutextree_mutex.mutex_id = _next_mutex_id++; _mutextree_mutex.mutex_id = _next_mutex_id++;
avl_insert(_mutextree, (void *)&_mutextree_mutex); avl_insert(_mutextree, (void *)&_mutextree_mutex);
#endif #endif
thread_mutex_create(&_threadtree_mutex); thread_mutex_create(&_threadtree_mutex);
thread_mutex_create(&_library_mutex); thread_mutex_create(&_library_mutex);
/* initialize the thread tree and insert the main thread */ /* initialize the thread tree and insert the main thread */
_threadtree = avl_tree_new(_compare_threads, NULL); _threadtree = avl_tree_new(_compare_threads, NULL);
thread = (thread_type *)malloc(sizeof(thread_type)); thread = (thread_type *)malloc(sizeof(thread_type));
thread->thread_id = _next_thread_id++; thread->thread_id = _next_thread_id++;
thread->line = 0; thread->line = 0;
thread->file = strdup("main.c"); thread->file = strdup("main.c");
thread->sys_thread = pthread_self(); thread->sys_thread = pthread_self();
thread->create_time = time(NULL); thread->create_time = time(NULL);
thread->name = strdup("Main Thread"); thread->name = strdup("Main Thread");
avl_insert(_threadtree, (void *)thread); avl_insert(_threadtree, (void *)thread);
_catch_signals(); _catch_signals();
_initialized = 1; _initialized = 1;
} }
void thread_shutdown(void) void thread_shutdown(void)
{ {
if (_initialized == 1) { if (_initialized == 1) {
thread_mutex_destroy(&_library_mutex); thread_mutex_destroy(&_library_mutex);
thread_mutex_destroy(&_threadtree_mutex); thread_mutex_destroy(&_threadtree_mutex);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
thread_mutex_destroy(&_mutextree_mutex); thread_mutex_destroy(&_mutextree_mutex);
avl_tree_free(_mutextree, _free_mutex); avl_tree_free(_mutextree, _free_mutex);
#endif #endif
avl_tree_free(_threadtree, _free_thread); avl_tree_free(_threadtree, _free_thread);
} }
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
log_close(_logid); log_close(_logid);
log_shutdown(); log_shutdown();
#endif #endif
} }
@ -268,44 +268,44 @@ static void _catch_signals(void)
thread_type *thread_create_c(char *name, void *(*start_routine)(void *), thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
void *arg, int detached, int line, char *file) void *arg, int detached, int line, char *file)
{ {
int created; int created;
thread_type *thread; thread_type *thread;
thread_start_t *start; thread_start_t *start;
thread = (thread_type *)malloc(sizeof(thread_type)); thread = (thread_type *)malloc(sizeof(thread_type));
start = (thread_start_t *)malloc(sizeof(thread_start_t)); start = (thread_start_t *)malloc(sizeof(thread_start_t));
thread->line = line; thread->line = line;
thread->file = strdup(file); thread->file = strdup(file);
_mutex_lock(&_threadtree_mutex); _mutex_lock(&_threadtree_mutex);
thread->thread_id = _next_thread_id++; thread->thread_id = _next_thread_id++;
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
thread->name = strdup(name); thread->name = strdup(name);
thread->create_time = time(NULL); thread->create_time = time(NULL);
thread->detached = 0; thread->detached = 0;
start->start_routine = start_routine; start->start_routine = start_routine;
start->arg = arg; start->arg = arg;
start->thread = thread; start->thread = thread;
start->detached = detached; start->detached = detached;
created = 0; created = 0;
if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0) if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0)
created = 1; created = 1;
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
else else
LOG_ERROR("Could not create new thread"); LOG_ERROR("Could not create new thread");
#endif #endif
if (created == 0) { if (created == 0) {
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_ERROR("System won't let me create more threads, giving up"); LOG_ERROR("System won't let me create more threads, giving up");
#endif #endif
return NULL; return NULL;
} }
return thread; return thread;
} }
/* _mutex_create /* _mutex_create
@ -315,193 +315,193 @@ thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
static void _mutex_create(mutex_t *mutex) static void _mutex_create(mutex_t *mutex)
{ {
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
mutex->thread_id = MUTEX_STATE_NEVERLOCKED; mutex->thread_id = MUTEX_STATE_NEVERLOCKED;
mutex->line = -1; mutex->line = -1;
#endif #endif
pthread_mutex_init(&mutex->sys_mutex, NULL); pthread_mutex_init(&mutex->sys_mutex, NULL);
} }
void thread_mutex_create_c(mutex_t *mutex, int line, char *file) void thread_mutex_create_c(mutex_t *mutex, int line, char *file)
{ {
_mutex_create(mutex); _mutex_create(mutex);
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
mutex->mutex_id = _next_mutex_id++; mutex->mutex_id = _next_mutex_id++;
avl_insert(_mutextree, (void *)mutex); avl_insert(_mutextree, (void *)mutex);
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
#endif #endif
} }
void thread_mutex_destroy (mutex_t *mutex) void thread_mutex_destroy (mutex_t *mutex)
{ {
pthread_mutex_destroy(&mutex->sys_mutex); pthread_mutex_destroy(&mutex->sys_mutex);
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
avl_delete(_mutextree, mutex, _free_mutex); avl_delete(_mutextree, mutex, _free_mutex);
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
#endif #endif
} }
void thread_mutex_lock_c(mutex_t *mutex, int line, char *file) void thread_mutex_lock_c(mutex_t *mutex, int line, char *file)
{ {
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
thread_type *th = thread_self(); thread_type *th = thread_self();
if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line); if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line);
LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
# ifdef CHECK_MUTEXES # ifdef CHECK_MUTEXES
/* Just a little sanity checking to make sure that we're locking /* Just a little sanity checking to make sure that we're locking
** mutexes correctly ** mutexes correctly
*/ */
if (th) { if (th) {
int locks = 0; int locks = 0;
avl_node *node; avl_node *node;
mutex_t *tmutex; mutex_t *tmutex;
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
node = avl_get_first (_mutextree); node = avl_get_first (_mutextree);
while (node) { while (node) {
tmutex = (mutex_t *)node->key; tmutex = (mutex_t *)node->key;
if (tmutex->mutex_id == mutex->mutex_id) { if (tmutex->mutex_id == mutex->mutex_id) {
if (tmutex->thread_id == th->thread_id) { if (tmutex->thread_id == th->thread_id) {
/* Deadlock, same thread can't lock the same mutex twice */ /* Deadlock, same thread can't lock the same mutex twice */
LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]",
tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
return; return;
} }
} else if (tmutex->thread_id == th->thread_id) { } else if (tmutex->thread_id == th->thread_id) {
/* Mutex locked by this thread (not this mutex) */ /* Mutex locked by this thread (not this mutex) */
locks++; locks++;
} }
node = avl_get_next(node); node = avl_get_next(node);
} }
if (locks > 0) { if (locks > 0) {
/* Has already got a mutex locked */ /* Has already got a mutex locked */
if (_multi_mutex.thread_id != th->thread_id) { if (_multi_mutex.thread_id != th->thread_id) {
/* Tries to lock two mutexes, but has not got the double mutex, norty boy! */ /* Tries to lock two mutexes, but has not got the double mutex, norty boy! */
LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!", LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!",
_multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
} }
} }
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
} }
# endif /* CHECK_MUTEXES */ # endif /* CHECK_MUTEXES */
_mutex_lock(mutex); _mutex_lock(mutex);
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1); LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1);
mutex->line = line; mutex->line = line;
if (th) { if (th) {
mutex->thread_id = th->thread_id; mutex->thread_id = th->thread_id;
} }
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
#else #else
_mutex_lock(mutex); _mutex_lock(mutex);
#endif /* DEBUG_MUTEXES */ #endif /* DEBUG_MUTEXES */
} }
void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file) void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file)
{ {
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
thread_type *th = thread_self(); thread_type *th = thread_self();
if (!th) { if (!th) {
LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line); LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line);
} }
LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
mutex->line = line; mutex->line = line;
# ifdef CHECK_MUTEXES # ifdef CHECK_MUTEXES
if (th) { if (th) {
int locks = 0; int locks = 0;
avl_node *node; avl_node *node;
mutex_t *tmutex; mutex_t *tmutex;
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
while (node) { while (node) {
tmutex = (mutex_t *)node->key; tmutex = (mutex_t *)node->key;
if (tmutex->mutex_id == mutex->mutex_id) { if (tmutex->mutex_id == mutex->mutex_id) {
if (tmutex->thread_id != th->thread_id) { if (tmutex->thread_id != th->thread_id) {
LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id,
mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
return; return;
} }
} else if (tmutex->thread_id == th->thread_id) { } else if (tmutex->thread_id == th->thread_id) {
locks++; locks++;
} }
node = avl_get_next (node); node = avl_get_next (node);
} }
if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) { if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) {
/* Don't have double mutex, has more than this mutex left */ /* Don't have double mutex, has more than this mutex left */
LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!", LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!",
_multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
} }
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
} }
# endif /* CHECK_MUTEXES */ # endif /* CHECK_MUTEXES */
_mutex_unlock(mutex); _mutex_unlock(mutex);
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1);
mutex->line = -1; mutex->line = -1;
if (mutex->thread_id == th->thread_id) { if (mutex->thread_id == th->thread_id) {
mutex->thread_id = MUTEX_STATE_NOTLOCKED; mutex->thread_id = MUTEX_STATE_NOTLOCKED;
} }
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
#else #else
_mutex_unlock(mutex); _mutex_unlock(mutex);
#endif /* DEBUG_MUTEXES */ #endif /* DEBUG_MUTEXES */
} }
void thread_cond_create_c(cond_t *cond, int line, char *file) void thread_cond_create_c(cond_t *cond, int line, char *file)
{ {
pthread_cond_init(&cond->sys_cond, NULL); pthread_cond_init(&cond->sys_cond, NULL);
pthread_mutex_init(&cond->cond_mutex, NULL); pthread_mutex_init(&cond->cond_mutex, NULL);
} }
void thread_cond_destroy(cond_t *cond) void thread_cond_destroy(cond_t *cond)
{ {
pthread_mutex_destroy(&cond->cond_mutex); pthread_mutex_destroy(&cond->cond_mutex);
pthread_cond_destroy(&cond->sys_cond); pthread_cond_destroy(&cond->sys_cond);
} }
void thread_cond_signal_c(cond_t *cond, int line, char *file) void thread_cond_signal_c(cond_t *cond, int line, char *file)
{ {
pthread_cond_signal(&cond->sys_cond); pthread_cond_signal(&cond->sys_cond);
} }
void thread_cond_broadcast_c(cond_t *cond, int line, char *file) void thread_cond_broadcast_c(cond_t *cond, int line, char *file)
{ {
pthread_cond_broadcast(&cond->sys_cond); pthread_cond_broadcast(&cond->sys_cond);
} }
void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file) void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file)
@ -518,223 +518,223 @@ void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file)
void thread_cond_wait_c(cond_t *cond, int line, char *file) void thread_cond_wait_c(cond_t *cond, int line, char *file)
{ {
pthread_mutex_lock(&cond->cond_mutex); pthread_mutex_lock(&cond->cond_mutex);
pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex); pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex);
pthread_mutex_unlock(&cond->cond_mutex); pthread_mutex_unlock(&cond->cond_mutex);
} }
void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file) void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file)
{ {
pthread_rwlock_init(&rwlock->sys_rwlock, NULL); pthread_rwlock_init(&rwlock->sys_rwlock, NULL);
} }
void thread_rwlock_destroy(rwlock_t *rwlock) void thread_rwlock_destroy(rwlock_t *rwlock)
{ {
pthread_rwlock_destroy(&rwlock->sys_rwlock); pthread_rwlock_destroy(&rwlock->sys_rwlock);
} }
void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file) void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file)
{ {
pthread_rwlock_rdlock(&rwlock->sys_rwlock); pthread_rwlock_rdlock(&rwlock->sys_rwlock);
} }
void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file) void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file)
{ {
pthread_rwlock_wrlock(&rwlock->sys_rwlock); pthread_rwlock_wrlock(&rwlock->sys_rwlock);
} }
void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file) void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file)
{ {
pthread_rwlock_unlock(&rwlock->sys_rwlock); pthread_rwlock_unlock(&rwlock->sys_rwlock);
} }
void thread_exit_c(int val, int line, char *file) void thread_exit_c(int val, int line, char *file)
{ {
thread_type *th = thread_self(); thread_type *th = thread_self();
#if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES) #if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES)
if (th) { if (th) {
avl_node *node; avl_node *node;
mutex_t *tmutex; mutex_t *tmutex;
char name[40]; char name[40];
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
while (node) { while (node) {
tmutex = (mutex_t *)node->key; tmutex = (mutex_t *)node->key;
if (tmutex->thread_id == th->thread_id) { if (tmutex->thread_id == th->thread_id) {
LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]", LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]",
th->thread_id, th->name, file, line, mutex_to_string(tmutex, name)); th->thread_id, th->name, file, line, mutex_to_string(tmutex, name));
} }
node = avl_get_next (node); node = avl_get_next (node);
} }
_mutex_unlock(&_mutextree_mutex); _mutex_unlock(&_mutextree_mutex);
} }
#endif #endif
if (th) { if (th) {
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line);
#endif #endif
_mutex_lock(&_threadtree_mutex); _mutex_lock(&_threadtree_mutex);
avl_delete(_threadtree, th, _free_thread_if_detached); avl_delete(_threadtree, th, _free_thread_if_detached);
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
} }
pthread_exit((void *)val); pthread_exit((void *)val);
} }
/* sleep for a number of microseconds */ /* sleep for a number of microseconds */
void thread_sleep(unsigned long len) void thread_sleep(unsigned long len)
{ {
#ifdef _WIN32 #ifdef _WIN32
Sleep(len / 1000); Sleep(len / 1000);
#else #else
# ifdef HAVE_NANOSLEEP # ifdef HAVE_NANOSLEEP
struct timespec time_sleep; struct timespec time_sleep;
struct timespec time_remaining; struct timespec time_remaining;
int ret; int ret;
time_sleep.tv_sec = len / 1000000; time_sleep.tv_sec = len / 1000000;
time_sleep.tv_nsec = (len % 1000000) * 1000; time_sleep.tv_nsec = (len % 1000000) * 1000;
ret = nanosleep(&time_sleep, &time_remaining); ret = nanosleep(&time_sleep, &time_remaining);
while (ret != 0 && errno == EINTR) { while (ret != 0 && errno == EINTR) {
time_sleep.tv_sec = time_remaining.tv_sec; time_sleep.tv_sec = time_remaining.tv_sec;
time_sleep.tv_nsec = time_remaining.tv_nsec; time_sleep.tv_nsec = time_remaining.tv_nsec;
ret = nanosleep(&time_sleep, &time_remaining); ret = nanosleep(&time_sleep, &time_remaining);
} }
# else # else
struct timeval tv; struct timeval tv;
tv.tv_sec = len / 1000000; tv.tv_sec = len / 1000000;
tv.tv_usec = (len % 1000000); tv.tv_usec = (len % 1000000);
select(0, NULL, NULL, NULL, &tv); select(0, NULL, NULL, NULL, &tv);
# endif # endif
#endif #endif
} }
static void *_start_routine(void *arg) static void *_start_routine(void *arg)
{ {
thread_start_t *start = (thread_start_t *)arg; thread_start_t *start = (thread_start_t *)arg;
void *(*start_routine)(void *) = start->start_routine; void *(*start_routine)(void *) = start->start_routine;
void *real_arg = start->arg; void *real_arg = start->arg;
thread_type *thread = start->thread; thread_type *thread = start->thread;
int detach = start->detached; int detach = start->detached;
_block_signals(); _block_signals();
free(start); free(start);
/* insert thread into thread tree here */ /* insert thread into thread tree here */
_mutex_lock(&_threadtree_mutex); _mutex_lock(&_threadtree_mutex);
thread->sys_thread = pthread_self(); thread->sys_thread = pthread_self();
avl_insert(_threadtree, (void *)thread); avl_insert(_threadtree, (void *)thread);
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line); LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line);
#endif #endif
if (detach) { if (detach) {
pthread_detach(thread->sys_thread); pthread_detach(thread->sys_thread);
thread->detached = 1; thread->detached = 1;
} }
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
/* call the real start_routine and start the thread /* call the real start_routine and start the thread
** this should never exit! ** this should never exit!
*/ */
(start_routine)(real_arg); (start_routine)(real_arg);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_WARN("Thread x should never exit from here!!!"); LOG_WARN("Thread x should never exit from here!!!");
#endif #endif
return NULL; return NULL;
} }
thread_type *thread_self(void) thread_type *thread_self(void)
{ {
avl_node *node; avl_node *node;
thread_type *th; thread_type *th;
pthread_t sys_thread = pthread_self(); pthread_t sys_thread = pthread_self();
_mutex_lock(&_threadtree_mutex); _mutex_lock(&_threadtree_mutex);
if (_threadtree == NULL) { if (_threadtree == NULL) {
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_WARN("Thread tree is empty, this must be wrong!"); LOG_WARN("Thread tree is empty, this must be wrong!");
#endif #endif
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
return NULL; return NULL;
} }
node = avl_get_first(_threadtree); node = avl_get_first(_threadtree);
while (node) { while (node) {
th = (thread_type *)node->key; th = (thread_type *)node->key;
if (th && pthread_equal(sys_thread, th->sys_thread)) { if (th && pthread_equal(sys_thread, th->sys_thread)) {
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
return th; return th;
} }
node = avl_get_next(node); node = avl_get_next(node);
} }
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_ERROR("Nonexistant thread alive..."); LOG_ERROR("Nonexistant thread alive...");
#endif #endif
return NULL; return NULL;
} }
void thread_rename(const char *name) void thread_rename(const char *name)
{ {
thread_type *th; thread_type *th;
th = thread_self(); th = thread_self();
if (th->name) free(th->name); if (th->name) free(th->name);
th->name = strdup(name); th->name = strdup(name);
} }
static void _mutex_lock(mutex_t *mutex) static void _mutex_lock(mutex_t *mutex)
{ {
pthread_mutex_lock(&mutex->sys_mutex); pthread_mutex_lock(&mutex->sys_mutex);
} }
static void _mutex_unlock(mutex_t *mutex) static void _mutex_unlock(mutex_t *mutex)
{ {
pthread_mutex_unlock(&mutex->sys_mutex); pthread_mutex_unlock(&mutex->sys_mutex);
} }
void thread_library_lock(void) void thread_library_lock(void)
{ {
_mutex_lock(&_library_mutex); _mutex_lock(&_library_mutex);
} }
void thread_library_unlock(void) void thread_library_unlock(void)
{ {
_mutex_unlock(&_library_mutex); _mutex_unlock(&_library_mutex);
} }
void thread_join(thread_type *thread) void thread_join(thread_type *thread)
{ {
void *ret; void *ret;
int i; int i;
i = pthread_join(thread->sys_thread, &ret); i = pthread_join(thread->sys_thread, &ret);
_mutex_lock(&_threadtree_mutex); _mutex_lock(&_threadtree_mutex);
avl_delete(_threadtree, thread, _free_thread); avl_delete(_threadtree, thread, _free_thread);
_mutex_unlock(&_threadtree_mutex); _mutex_unlock(&_threadtree_mutex);
@ -745,65 +745,65 @@ void thread_join(thread_type *thread)
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
static int _compare_mutexes(void *compare_arg, void *a, void *b) static int _compare_mutexes(void *compare_arg, void *a, void *b)
{ {
mutex_t *m1, *m2; mutex_t *m1, *m2;
m1 = (mutex_t *)a; m1 = (mutex_t *)a;
m2 = (mutex_t *)b; m2 = (mutex_t *)b;
if (m1->mutex_id > m2->mutex_id) if (m1->mutex_id > m2->mutex_id)
return 1; return 1;
if (m1->mutex_id < m2->mutex_id) if (m1->mutex_id < m2->mutex_id)
return -1; return -1;
return 0; return 0;
} }
#endif #endif
static int _compare_threads(void *compare_arg, void *a, void *b) static int _compare_threads(void *compare_arg, void *a, void *b)
{ {
thread_type *t1, *t2; thread_type *t1, *t2;
t1 = (thread_type *)a; t1 = (thread_type *)a;
t2 = (thread_type *)b; t2 = (thread_type *)b;
if (t1->thread_id > t2->thread_id) if (t1->thread_id > t2->thread_id)
return 1; return 1;
if (t1->thread_id < t2->thread_id) if (t1->thread_id < t2->thread_id)
return -1; return -1;
return 0; return 0;
} }
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
static int _free_mutex(void *key) static int _free_mutex(void *key)
{ {
mutex_t *m; mutex_t *m;
m = (mutex_t *)key; m = (mutex_t *)key;
if (m && m->file) { if (m && m->file) {
free(m->file); free(m->file);
m->file = NULL; m->file = NULL;
} }
/* all mutexes are static. don't need to free them */ /* all mutexes are static. don't need to free them */
return 1; return 1;
} }
#endif #endif
static int _free_thread(void *key) static int _free_thread(void *key)
{ {
thread_type *t; thread_type *t;
t = (thread_type *)key; t = (thread_type *)key;
if (t->file) if (t->file)
free(t->file); free(t->file);
if (t->name) if (t->name)
free(t->name); free(t->name);
free(t); free(t);
return 1; return 1;
} }
static int _free_thread_if_detached(void *key) static int _free_thread_if_detached(void *key)

View File

@ -27,67 +27,67 @@
/* renamed from thread_t due to conflict on OS X */ /* renamed from thread_t due to conflict on OS X */
typedef struct { typedef struct {
/* the local id for the thread, and it's name */ /* the local id for the thread, and it's name */
long thread_id; long thread_id;
char *name; char *name;
/* the time the thread was created */ /* the time the thread was created */
time_t create_time; time_t create_time;
/* the file and line which created this thread */ /* the file and line which created this thread */
char *file; char *file;
int line; int line;
/* is the thread running detached? */ /* is the thread running detached? */
int detached; int detached;
/* the system specific thread */ /* the system specific thread */
pthread_t sys_thread; pthread_t sys_thread;
} thread_type; } thread_type;
typedef struct { typedef struct {
#ifdef DEBUG_MUTEXES #ifdef DEBUG_MUTEXES
/* the local id and name of the mutex */ /* the local id and name of the mutex */
long mutex_id; long mutex_id;
char *name; char *name;
/* the thread which is currently locking this mutex */ /* the thread which is currently locking this mutex */
long thread_id; long thread_id;
/* the file and line where the mutex was locked */ /* the file and line where the mutex was locked */
char *file; char *file;
int line; int line;
#endif #endif
/* the system specific mutex */ /* the system specific mutex */
pthread_mutex_t sys_mutex; pthread_mutex_t sys_mutex;
} mutex_t; } mutex_t;
typedef struct { typedef struct {
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
long cond_id; long cond_id;
char *name; char *name;
#endif #endif
pthread_mutex_t cond_mutex; pthread_mutex_t cond_mutex;
pthread_cond_t sys_cond; pthread_cond_t sys_cond;
} cond_t; } cond_t;
typedef struct { typedef struct {
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
long rwlock_id; long rwlock_id;
char *name; char *name;
/* information on which thread and where in the code /* information on which thread and where in the code
** this rwlock was write locked ** this rwlock was write locked
*/ */
long thread_id; long thread_id;
char *file; char *file;
int line; int line;
#endif #endif
pthread_rwlock_t sys_rwlock; pthread_rwlock_t sys_rwlock;
} rwlock_t; } rwlock_t;
#define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__) #define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__)

View File

@ -28,27 +28,27 @@
uint64_t timing_get_time(void) uint64_t timing_get_time(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
return timeGetTime(); return timeGetTime();
#else #else
struct timeval mtv; struct timeval mtv;
gettimeofday(&mtv, NULL); gettimeofday(&mtv, NULL);
return (uint64_t)(mtv.tv_sec) * 1000 + (uint64_t)(mtv.tv_usec) / 1000; return (uint64_t)(mtv.tv_sec) * 1000 + (uint64_t)(mtv.tv_usec) / 1000;
#endif #endif
} }
void timing_sleep(uint64_t sleeptime) void timing_sleep(uint64_t sleeptime)
{ {
struct timeval sleeper; struct timeval sleeper;
sleeper.tv_sec = sleeptime / 1000; sleeper.tv_sec = sleeptime / 1000;
sleeper.tv_usec = (sleeptime % 1000) * 1000; sleeper.tv_usec = (sleeptime % 1000) * 1000;
/* NOTE: /* NOTE:
* This should be 0 for the first argument. The linux manpage * This should be 0 for the first argument. The linux manpage
* says so. The solaris manpage also says this is a legal * says so. The solaris manpage also says this is a legal
* value. If you think differerntly, please provide references. * value. If you think differerntly, please provide references.
*/ */
select(0, NULL, NULL, NULL, &sleeper); select(0, NULL, NULL, NULL, &sleeper);
} }