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:
parent
da0d5f93fe
commit
b9a0753da8
86
src/accept.c
86
src/accept.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
25
src/config.c
25
src/config.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
59
src/filter.c
59
src/filter.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
37
src/worker.c
37
src/worker.c
|
|
@ -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--;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue