some of data structure alloc/free codes modularized; filter preparsing

git-svn-id: http://repo.ham.fi/svn/aprsc/trunk@22 3ce903b1-3385-4e86-93cd-f9a4a239f7ac
This commit is contained in:
Matti Aarnio 2008-02-28 22:15:55 +00:00
parent da0d5f93fe
commit b9a0753da8
6 changed files with 161 additions and 52 deletions

View File

@ -25,6 +25,7 @@
#include "netlib.h"
#include "worker.h"
#include "dupecheck.h"
#include "filter.h"
struct listen_t {
struct listen_t *next;
@ -35,6 +36,7 @@ struct listen_t {
int fd;
char *addr_s;
char *filters[10];
} *listen_list = NULL;
pthread_mutex_t mt_servercount = PTHREAD_MUTEX_INITIALIZER;
@ -42,6 +44,33 @@ pthread_mutex_t mt_servercount = PTHREAD_MUTEX_INITIALIZER;
int accept_reconfiguring = 0;
int accept_shutting_down = 0;
/* structure allocator/free */
struct listen_t *listener_alloc(void)
{
struct listen_t *l = hmalloc(sizeof(*l));
memset((void *)l, 0, sizeof(*l));
l->fd = -1;
return l;
}
void listener_free(struct listen_t *l)
{
int i;
if (l->fd >= 0) close(l->fd);
if (l->addr_s) hfree(l->addr_s);
for (i = 0; i < (sizeof(l->filters)/sizeof(l->filters[0])); ++i)
if (l->filters[i])
hfree(l->filters[i]);
hfree(l);
}
/*
* signal handler
*/
@ -101,11 +130,11 @@ int open_listeners(void)
struct listen_t *l;
struct hostent *he;
char eb[80];
int opened = 0;
int opened = 0, i;
for (lc = listen_config; (lc); lc = lc->next) {
l = hmalloc(sizeof(*l));
l->fd = -1;
l = listener_alloc();
l->sin.sin_family = AF_INET;
l->sin.sin_port = htons(lc->port);
@ -113,7 +142,7 @@ int open_listeners(void)
if (!(he = gethostbyname(lc->host))) {
h_strerror(h_errno, eb, sizeof(eb));
hlog(LOG_CRIT, "Listen: Could not resolve \"%s\": %s - not listening on port %d\n", lc->host, eb, lc->port);
hfree(l);
listener_free(l);
continue;
}
memcpy(&l->sin.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
@ -129,11 +158,18 @@ int open_listeners(void)
hlog(LOG_DEBUG, "... ok, bound");
} else {
hlog(LOG_DEBUG, "... failed");
hfree(l->addr_s);
hfree(l);
listener_free(l);
continue;
}
/* Copy filter definitions */
for (i = 0; i < (sizeof(l->filters)/sizeof(l->filters[0])); ++i) {
if (i < (sizeof(lc->filters)/sizeof(lc->filters[0])))
l->filters[i] = lc->filters[i];
else
l->filters[i] = NULL;
}
hlog(LOG_DEBUG, "... adding to listened sockets");
// put (first) in the list of listening sockets
l->next = listen_list;
@ -156,13 +192,12 @@ void close_listeners(void)
while (listen_list) {
l = listen_list;
listen_list = listen_list->next;
if (l->fd >= 0)
close(l->fd);
hfree(l->addr_s);
hfree(l);
listener_free(l);
}
}
/*
* Accept a single connection
*/
@ -170,11 +205,13 @@ void close_listeners(void)
struct client_t *do_accept(struct listen_t *l)
{
char eb[80];
struct client_t *c = hmalloc(sizeof(*c));
memset((void *)c, 0, sizeof(*c));
c->addr_len = sizeof(c->addr);
int fd, i;
struct client_t *c;
struct sockaddr_in *sin;
struct sockaddr sa;
socklen_t addr_len = sizeof(sa);
if ((c->fd = accept(l->fd, &c->addr, &c->addr_len)) < 0) {
if ((fd = accept(l->fd, &sa, &addr_len)) < 0) {
int e = errno;
switch (e) {
/* Errors reporting really bad internal (programming) bugs */
@ -194,7 +231,6 @@ struct client_t *do_accept(struct listen_t *l)
#endif
hlog(LOG_CRIT, "accept() failed: %s (giving up)", strerror(e));
hfree(c);
exit(1); // ABORT with core-dump ??
break;
@ -202,20 +238,22 @@ struct client_t *do_accept(struct listen_t *l)
/* Errors reporting system internal/external glitches */
default:
hlog(LOG_ERR, "accept() failed: %s (continuing)", strerror(e));
hfree(c);
return NULL;
}
}
struct sockaddr_in *sin = (struct sockaddr_in *)&c->addr;
c = client_alloc();
sin = (struct sockaddr_in *)&c->addr;
aptoa(sin->sin_addr, ntohs(sin->sin_port), eb, sizeof(eb));
c->addr_s = hstrdup(eb);
c->ibuf_size = ibuf_size;
c->ibuf = hmalloc(c->ibuf_size);
c->obuf_size = obuf_size;
c->obuf = hmalloc(c->obuf_size);
hlog(LOG_DEBUG, "%s - Accepted connection on fd %d from %s", l->addr_s, c->fd, eb);
for (i = 0; i < (sizeof(l->filters)/sizeof(l->filters[0])); ++i) {
if (l->filters[i])
filter_parse(c, l->filters[i]);
}
/* set non-blocking mode */
if (fcntl(c->fd, F_SETFL, O_NONBLOCK)) {
hlog(LOG_ERR, "%s - Failed to set non-blocking mode on socket: %s", l->addr_s, strerror(errno));
@ -259,9 +297,7 @@ struct client_t *do_accept(struct listen_t *l)
return c;
err:
close(c->fd);
hfree(c->ibuf);
hfree(c);
client_free(c);
return 0;
}

View File

@ -92,12 +92,16 @@ static struct cfgcmd cfg_cmds[] = {
void free_listen_config(struct listen_config_t **lc)
{
struct listen_config_t *this;
int i;
while (*lc) {
this = *lc;
*lc = this->next;
hfree(this->name);
hfree(this->host);
for (i = 0; i < (sizeof(this->filters)/sizeof(this->filters[0])); ++i)
if (this->filters[i])
hfree(this->filters[i]);
hfree(this);
}
}
@ -155,11 +159,17 @@ int do_interval(time_t *dest, int argc, char **argv)
/*
* Parse a Listen directive
*
* listen <label> <?> tcp <hostname> <portnum> [<filter> [..<more_filters>]]
*
*/
int do_listen(struct listen_config_t **lq, int argc, char **argv)
{
if (argc != 6)
int i, port;
struct listen_config_t *l;
if (argc < 6)
return -1;
if (strcasecmp(argv[3], "tcp") == 0) {
@ -169,16 +179,23 @@ int do_listen(struct listen_config_t **lq, int argc, char **argv)
return -2;
}
int port = atoi(argv[5]);
port = atoi(argv[5]);
if (port < 1 || port > 65535) {
fprintf(stderr, "Listen: unsupported port number '%s'\n", argv[5]);
return -2;
}
struct listen_config_t *l = hmalloc(sizeof(*l));
l = hmalloc(sizeof(*l));
l->name = hstrdup(argv[1]);
l->host = hstrdup(argv[4]);
l->port = port;
for (i = 0; i < (sizeof(l->filters)/sizeof(l->filters[0])); ++i) {
l->filters[i] = NULL;
if (argc - 6 >= i) {
l->filters[i] = hstrdup(argv[i+6]);
}
}
/* put in the list */
l->next = *lq;

View File

@ -47,6 +47,8 @@ struct listen_config_t {
char *name; /* name of socket */
char *host; /* hostname or dotted-quad IP to bind the UDP socket to, default INADDR_ANY */
int port; /* port to bind */
char *filters[10]; /* up to 10 filters, NULL when not defined */
};
extern struct listen_config_t *listen_config;

View File

@ -33,7 +33,8 @@
struct filter_t {
struct filter_t *next;
int type; /* 1 char */
char type; /* 1 char */
char negate; /* boolean flag */
const char *text; /* filter text as is */
float f[4]; /* parsed floats, if any */
};
@ -41,42 +42,68 @@ struct filter_t {
int filter_parse(struct client_t *c, char *filt)
{
struct filter_t *f = hmalloc(sizeof(*f));
struct filter_t *f, f0;
struct filter_t **ff = & c->filterhead;
int i;
if (!f) return -1;
memset(f, 0, sizeof(*f));
f->text = hstrdup(filt);
f->type = *filt;
/* link to the tail.. */
while (*ff != NULL)
ff = &((*ff)->next);
*ff = f;
memset(&f0, 0, sizeof(f0));
if (*filt == '-') {
f0.negate = 1;
++filt;
}
f0.type = *filt;
if (!strchr("abdeopqrstu",*filt)) {
/* Not valid filter code */
return -1;
}
switch (f->type) {
switch (f0.type) {
case 'a':
/* a/latN/lonW/latS/lonE Area filter */
i = sscanf(filt, "a/%f/%f/%f/%f",
&f->f[0],&f->f[1],&f->f[2],&f->f[3]);
&f0.f[0],&f0.f[1],&f0.f[2],&f0.f[3]);
if (i != 4) return -1;
return 0;
if (!( -90.01 < f0.f[0] && f0.f[0] < 90.01)) return -2;
if (!(-180.01 < f0.f[1] && f0.f[1] < 180.01)) return -2;
if (!( -90.01 < f0.f[2] && f0.f[2] < 90.01)) return -2;
if (!(-180.01 < f0.f[3] && f0.f[3] < 180.01)) return -2;
if (f0.f[0] < f0.f[2]) return -3; /* expect: latN >= latS */
if (f0.f[1] > f0.f[3]) return -3; /* expect: lonW <= lonE */
f0.f[0] *= (3.1415926/180.0); /* deg-to-radians */
f0.f[1] *= (3.1415926/180.0); /* deg-to-radians */
f0.f[2] *= (3.1415926/180.0); /* deg-to-radians */
f0.f[3] *= (3.1415926/180.0); /* deg-to-radians */
break;
case 'r':
/* r/lat/lon/dist Range filter */
i = sscanf(filt, "r/%f/%f/%f",
&f->f[0],&f->f[1],&f->f[2]);
&f0.f[0],&f0.f[1],&f0.f[2]);
if (i != 3) return -1;
return 0;
if (!( -90.01 < f0.f[0] && f0.f[0] < 90.01)) return -2;
if (!(-180.01 < f0.f[1] && f0.f[1] < 180.01)) return -2;
f0.f[0] *= (3.1415926/180.0); /* deg-to-radians */
f0.f[1] *= (3.1415926/180.0); /* deg-to-radians */
break;
default:;
break;
}
/* OK, pre-parsing produced accepted result */
f = hmalloc(sizeof(*f));
if (!f) return -1;
*f = f0; /* store pre-parsed values */
f->text = hstrdup(filt); /* and copy of filter text */
/* link to the tail.. */
while (*ff != NULL)
ff = &((*ff)->next);
*ff = f;
return 0;
}

View File

@ -37,6 +37,36 @@ struct pbuf_t *pbuf_global = NULL;
struct pbuf_t *pbuf_global_last = NULL;
struct pbuf_t **pbuf_global_prevp = &pbuf_global;
/* object alloc/free */
struct client_t *client_alloc(void)
{
struct client_t *c = hmalloc(sizeof(*c));
memset((void *)c, 0, sizeof(*c));
c->fd = -1;
c->ibuf_size = ibuf_size;
c->ibuf = hmalloc(c->ibuf_size);
c->obuf_size = obuf_size;
c->obuf = hmalloc(c->obuf_size);
return c;
}
void client_free(struct client_t *c)
{
if (c->fd >= 0) close(c->fd);
if (c->ibuf) hfree(c->ibuf);
if (c->obuf) hfree(c->obuf);
if (c->addr_s) hfree(c->addr_s);
filter_free(c->filterhead);
hfree(c);
}
/*
* signal handler
*/
@ -74,12 +104,7 @@ void close_client(struct worker_t *self, struct client_t *c)
*c->prevp = c->next;
/* free it up */
hfree(c->addr_s);
hfree(c->username);
hfree(c->ibuf);
hfree(c->obuf);
filter_free(c->filterhead);
hfree(c);
client_free(c);
/* reduce client counter */
self->client_count--;

View File

@ -103,7 +103,6 @@ struct client_t {
struct client_t **prevp;
struct sockaddr addr;
socklen_t addr_len;
int fd;
int udp_port;
char *addr_s;
@ -135,6 +134,9 @@ struct client_t {
struct filter_t *filterhead;
};
extern struct client_t *client_alloc(void);
extern void client_free(struct client_t *c);
/* worker thread structure */
struct worker_t {