Commit 3659d183 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Introduce new library for generic command handling.

It contains code now duplicated in several trackers.
This is step 1:
-create library
-use in the moon tracker.

Todo:
step 2:
-move other trackers
-Improve library code.
parent 22055514
......@@ -5,7 +5,8 @@ LDFLAGS= -lpthread
CFLAGS+=`pkg-config --cflags glib-2.0`
LDFLAGS+=`pkg-config --libs glib-2.0`
UTILSRCS= tcp_connect.c tcp_listen.c config.c weather.c dt_model.c location.c dt_host.c
UTILSRCS= tcp_connect.c tcp_listen.c command_server.c \
config.c weather.c dt_model.c location.c dt_host.c
LIBUTILOBJS= $(UTILSRCS:.c=.lo)
all: $(LIBUTILOBJS) weather_test libutils.la libutils.la_install
......
/*
Command server
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2013
Copyright Stichting C.A. Muller Radioastronomiestation, 2013
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include "tcp_listen.h"
struct command_client {
struct command_client *next;
int fd;
char buffer[200];
int buflen;
};
struct command_server {
int fd;
struct command_client *clients;
int (*handle_func)(char *name, char *value);
};
static int default_func(char *name, char *value)
{
printf("No command handler installed!!!");
return -1;
}
struct command_server *command_server_create(int port, int local, int backlog)
{
struct command_server *srv;
srv = calloc(1, sizeof(struct command_server));
if (!srv)
goto err_alloc;
srv->fd = tcp_listen(port, local, backlog);
if (srv->fd < 0)
goto err_listen;
ioctl(srv->fd, FIONBIO, &(int){ 1 });
srv->handle_func = default_func;
return srv;
err_listen:
close(srv->fd);
err_alloc:
return NULL;
}
void command_server_destroy(struct command_server *srv)
{
if (srv) {
close(srv->fd);
free(srv);
}
}
int command_server_handler_set(struct command_server *srv,
int (*func)(char *name, char *value))
{
srv->handle_func = func;
return 0;
}
int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high)
{
struct command_client *client;
for (client = srv->clients; client; client = client->next) {
FD_SET(client->fd, set);
if (client->fd >= *high)
*high = client->fd + 1;
}
FD_SET(srv->fd, set);
if (srv->fd >= *high)
*high = srv->fd + 1;
return 0;
}
void command_server_handle(struct command_server *srv, struct command_client *client)
{
char *namevalue;
char *name;
char *value;
char *ptr;
namevalue = client->buffer;
name = strtok_r(namevalue, ",=", &ptr);
value = strtok_r(NULL, ",=", &ptr);
srv->handle_func(name, value);
}
int command_server_fdset_handle(struct command_server *srv, fd_set *set)
{
struct command_client *client, **clientp, **nextp;
for (clientp = &srv->clients; *clientp; clientp = nextp) {
nextp = &(*clientp)->next;
if (FD_ISSET((*clientp)->fd, set)) {
/* received something */
int ret;
do {
ret = read((*clientp)->fd, (*clientp)->buffer+(*clientp)->buflen, 1);
if ((ret < 0 && errno != EAGAIN) || ret == 0) {
client = *clientp;
close(client->fd);
*clientp = (*clientp)->next;
free(client);
nextp = clientp;
} else if (ret == 1) {
(*clientp)->buflen += 1;
if ((*clientp)->buffer[(*clientp)->buflen-1] == '\n' ||
(*clientp)->buffer[(*clientp)->buflen-1] == '\r') {
if ((*clientp)->buflen > 1) {
(*clientp)->buffer[(*clientp)->buflen] = 0;
command_server_handle(srv, *clientp);
(*clientp)->buffer[0] = '9';
}
(*clientp)->buflen = 0;
}
if ((*clientp)->buflen >= 200)
(*clientp)->buflen = 0;
}
} while (ret > 0);
}
}
if (FD_ISSET(srv->fd, set)) {
/* New client */
int client_fd;
client_fd = tcp_accept(srv->fd);
if (client_fd < 0)
return -1;
ioctl(client_fd, FIONBIO, &(int){ 1 });
client = calloc(1, sizeof(struct command_client));
if (!client) {
close(client_fd);
} else {
client->fd = client_fd;
client->buflen = 0;
client->next = srv->clients;
srv->clients = client;
}
}
return 0;
}
/*
Command server
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2013
Copyright Stichting C.A. Muller Radioastronomiestation, 2013
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INCLUDE_COMMAND_SERVER_
#define _INCLUDE_COMMAND_SERVER_
#include <sys/select.h>
struct command_server;
struct command_server *command_server_create(int port, int local, int backlog);
void command_server_destroy(struct command_server *srv);
int command_server_handler_set(struct command_server *srv,
int (*func)(char *name, char *value));
int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high);
int command_server_fdset_handle(struct command_server *srv, fd_set *set);
#endif /* _INCLUDE_COMMAND_SERVER_ */
......@@ -51,6 +51,8 @@
#include "dt_port_numbers.h"
#include "command_server.h"
char *command_host = "localhost";
int command_port = CONSOLE_COMMAND_PORT;
int stat_port = CONSOLE_MOON_STAT_PORT;
......@@ -89,15 +91,8 @@ struct stat_client {
struct stat_client *stat_clients = NULL;
struct cmd_client {
struct cmd_client *next;
int fd;
char buffer[200];
int buflen;
};
struct cmd_client *cmd_clients = NULL;
struct command_server *cmd_srv;
void new_stat_client(int fd_stat)
......@@ -121,102 +116,25 @@ void new_stat_client(int fd_stat)
stat_clients = new_stat;
}
void new_cmd_client(int fd_cmd)
{
struct cmd_client *new_cmd;
int fd;
fd = tcp_accept(fd_cmd);
if (fd < 0)
return;
ioctl(fd, FIONBIO, &(int){ 1 });
new_cmd = malloc(sizeof(struct cmd_client));
if (!new_cmd) {
close(fd);
return;
}
new_cmd->fd = fd;
new_cmd->buflen = 0;
new_cmd->next = cmd_clients;
cmd_clients = new_cmd;
}
void fdset_cmd_clients(fd_set *fdset_rx, int *high)
static int handle_cmd(char *name, char *val)
{
struct cmd_client *cmd;
for (cmd = cmd_clients; cmd; cmd = cmd->next) {
FD_SET(cmd->fd, fdset_rx);
if (cmd->fd >= *high)
*high = cmd->fd + 1;
}
}
int i;
void handle_cmd(struct cmd_client *cmd)
{
char *switches, *ptr;
switches = cmd->buffer;
printf("command: %s\n", switches);
if (switches) {
char *name, *val;
int i;
name = strtok_r(switches, ",=", &ptr);
val = strtok_r(NULL, ",=", &ptr);
printf("name %s value %s\n", name, val);
for (i = 0; compensation_switches[i].name; i++) {
if (!strcmp(name, compensation_switches[i].name)) {
printf("found switch %s\n", name);
if (val[0] == '1') {
*compensation_switches[i].value = true;
} else {
*compensation_switches[i].value = false;
}
printf("name %s value %s\n", name, val);
for (i = 0; compensation_switches[i].name; i++) {
if (!strcmp(name, compensation_switches[i].name)) {
printf("found switch %s\n", name);
if (val[0] == '1') {
*compensation_switches[i].value = true;
} else {
*compensation_switches[i].value = false;
}
}
}
return 0;
}
void check_cmd_clients(fd_set *fdset_rx)
{
struct cmd_client **cmdp, **nextp = NULL;
for (cmdp = &cmd_clients; *cmdp; cmdp = nextp) {
int ret;
nextp = &(*cmdp)->next;
if (!FD_ISSET((*cmdp)->fd, fdset_rx))
continue;
do {
ret = read((*cmdp)->fd, (*cmdp)->buffer+(*cmdp)->buflen, 1);
if ((ret < 0 && errno != EAGAIN) || ret == 0) {
struct cmd_client *tmp;
tmp = *cmdp;
close((*cmdp)->fd);
*cmdp = (*cmdp)->next;
free(tmp);
nextp = cmdp;
} else if (ret == 1) {
(*cmdp)->buflen += 1;
if ((*cmdp)->buffer[(*cmdp)->buflen-1] == '\n' ||
(*cmdp)->buffer[(*cmdp)->buflen-1] == '\r') {
if ((*cmdp)->buflen > 1) {
(*cmdp)->buffer[(*cmdp)->buflen] = 0;
handle_cmd(*cmdp);
(*cmdp)->buffer[0] = '9';
}
(*cmdp)->buflen = 0;
}
if ((*cmdp)->buflen >= 200)
(*cmdp)->buflen = 0;
}
} while (ret > 0);
}
}
void output(void)
{
......@@ -273,7 +191,7 @@ int main(int argc, char **argv)
struct setpoint_command *sp_command_az = NULL;
struct setpoint_command *sp_command_el = NULL;
struct weather *weather;
int fd_stat, fd_cmd;
int fd_stat;
time_t lastt = 0;
......@@ -300,11 +218,12 @@ int main(int argc, char **argv)
aalib_init();
fd_cmd = tcp_listen(cmd_port, 0, 100);
if (fd_cmd < 0) {
cmd_srv = command_server_create(cmd_port, 0, 100);
if (!cmd_srv) {
printf("Could not open listen port for commands\n");
} else {
ioctl(fd_cmd, FIONBIO, &(int){ 1 });
command_server_handler_set(cmd_srv, handle_cmd);
}
fd_stat = tcp_listen(stat_port, 0, 100);
if (fd_stat < 0) {
......@@ -375,12 +294,7 @@ int main(int argc, char **argv)
if (fd_stat >= high)
high = fd_stat + 1;
}
if (fd_cmd >= 0) {
FD_SET(fd_cmd, &fdset_rx);
if (fd_cmd >= high)
high = fd_cmd + 1;
}
fdset_cmd_clients(&fdset_rx, &high);
command_server_fdset_add(cmd_srv, &fdset_rx, &high);
tv.tv_sec = 1;
tv.tv_usec = 0;
......@@ -390,10 +304,8 @@ int main(int argc, char **argv)
if (FD_ISSET(fd_stat, &fdset_rx)) {
new_stat_client(fd_stat);
}
if (FD_ISSET(fd_cmd, &fdset_rx)) {
new_cmd_client(fd_cmd);
}
check_cmd_clients(&fdset_rx);
command_server_fdset_handle(cmd_srv, &fdset_rx);
output();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment