Commit 576e88b3 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Command server step 2: move all trackers to the new command server lib.

parent 3659d183
...@@ -40,6 +40,7 @@ struct command_server { ...@@ -40,6 +40,7 @@ struct command_server {
struct command_client *clients; struct command_client *clients;
int (*handle_func)(char *name, char *value); int (*handle_func)(char *name, char *value);
int (*handle_raw_func)(char *command);
}; };
...@@ -77,7 +78,17 @@ err_alloc: ...@@ -77,7 +78,17 @@ err_alloc:
void command_server_destroy(struct command_server *srv) void command_server_destroy(struct command_server *srv)
{ {
struct command_client *client;
if (srv) { if (srv) {
while (srv->clients) {
client = srv->clients;
srv->clients = client->next;
close(client->fd);
free(client);
}
close(srv->fd); close(srv->fd);
free(srv); free(srv);
} }
...@@ -87,13 +98,27 @@ void command_server_destroy(struct command_server *srv) ...@@ -87,13 +98,27 @@ void command_server_destroy(struct command_server *srv)
int command_server_handler_set(struct command_server *srv, int command_server_handler_set(struct command_server *srv,
int (*func)(char *name, char *value)) int (*func)(char *name, char *value))
{ {
/* Remember who to call when a command is received */
srv->handle_func = func; srv->handle_func = func;
return 0; return 0;
} }
int command_server_handler_raw_set(struct command_server *srv,
int (*func)(char *command))
{
/* Remember who to call when a command is received */
srv->handle_raw_func = func;
return 0;
}
int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high) int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high)
{ {
/* Add all our sockets to the set
*/
struct command_client *client; struct command_client *client;
for (client = srv->clients; client; client = client->next) { for (client = srv->clients; client; client = client->next) {
...@@ -111,16 +136,29 @@ int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high) ...@@ -111,16 +136,29 @@ int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high)
void command_server_handle(struct command_server *srv, struct command_client *client) void command_server_handle(struct command_server *srv, struct command_client *client)
{ {
/* A command has been received.
Split it in a key, value pair and pass it to application handler
Some applications have a command format which is not (completly) in
a key=value format. They can get the 'raw' string and still enjoy
the other benefits of this lib.
*/
char *namevalue; char *namevalue;
char *name; char *name;
char *value; char *value;
char *ptr; char *ptr;
if (srv->handle_raw_func) {
srv->handle_raw_func(client->buffer);
} else {
do {
namevalue = client->buffer; namevalue = client->buffer;
name = strtok_r(namevalue, ",=", &ptr); name = strtok_r(namevalue, ",=", &ptr);
value = strtok_r(NULL, ",=", &ptr); value = strtok_r(NULL, ",=", &ptr);
if (name && value)
srv->handle_func(name, value); srv->handle_func(name, value);
} while (name && value);
}
} }
int command_server_fdset_handle(struct command_server *srv, fd_set *set) int command_server_fdset_handle(struct command_server *srv, fd_set *set)
...@@ -138,12 +176,17 @@ int command_server_fdset_handle(struct command_server *srv, fd_set *set) ...@@ -138,12 +176,17 @@ int command_server_fdset_handle(struct command_server *srv, fd_set *set)
do { do {
ret = read((*clientp)->fd, (*clientp)->buffer+(*clientp)->buflen, 1); ret = read((*clientp)->fd, (*clientp)->buffer+(*clientp)->buflen, 1);
if ((ret < 0 && errno != EAGAIN) || ret == 0) { if ((ret < 0 && errno != EAGAIN) || ret == 0) {
/* Fatal error on socket to client.
Clean up client
*/
client = *clientp; client = *clientp;
close(client->fd); close(client->fd);
*clientp = (*clientp)->next; *clientp = (*clientp)->next;
free(client); free(client);
nextp = clientp; nextp = clientp;
} else if (ret == 1) { } else if (ret == 1) {
/* Data from client received.
*/
(*clientp)->buflen += 1; (*clientp)->buflen += 1;
if ((*clientp)->buffer[(*clientp)->buflen-1] == '\n' || if ((*clientp)->buffer[(*clientp)->buflen-1] == '\n' ||
(*clientp)->buffer[(*clientp)->buflen-1] == '\r') { (*clientp)->buffer[(*clientp)->buflen-1] == '\r') {
......
...@@ -31,6 +31,8 @@ void command_server_destroy(struct command_server *srv); ...@@ -31,6 +31,8 @@ void command_server_destroy(struct command_server *srv);
int command_server_handler_set(struct command_server *srv, int command_server_handler_set(struct command_server *srv,
int (*func)(char *name, char *value)); int (*func)(char *name, char *value));
int command_server_handler_raw_set(struct command_server *srv,
int (*func)(char *command));
int command_server_fdset_add(struct command_server *srv, fd_set *set, int *high); 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); int command_server_fdset_handle(struct command_server *srv, fd_set *set);
......
/* /*
Command generator for az/el positions Command generator for az/el positions
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2008 Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2008, 2013
Copyright Stichting C.A. Muller Radioastronomiestation, 2008 Copyright Stichting C.A. Muller Radioastronomiestation, 2008, 2013
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -38,8 +38,7 @@ ...@@ -38,8 +38,7 @@
#include "setpoint.h" #include "setpoint.h"
#include "tcp_connect.h" #include "command_server.h"
#include "tcp_listen.h"
char *command_host = "localhost"; char *command_host = "localhost";
int command_port = 11000; int command_port = 11000;
...@@ -57,58 +56,16 @@ typedef union { ...@@ -57,58 +56,16 @@ typedef union {
} float32_t; } float32_t;
struct cmd_client { int handle_cmd(char *command)
struct cmd_client *next;
int fd;
char buffer[100];
int buflen;
};
struct cmd_client *cmd_clients = NULL;
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)
{
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;
}
}
void handle_cmd(struct cmd_client *cmd)
{ {
char *aaz, *ael, *ptr; char *aaz, *ael, *ptr;
printf("cmd: '%s'\n", cmd->buffer); printf("cmd: '%s'\n", command);
aaz = strtok_r(cmd->buffer, " \t", &ptr); aaz = strtok_r(command, " \t", &ptr);
ael = strtok_r(NULL, " \t", &ptr); ael = strtok_r(NULL, " \t", &ptr);
if (!aaz || !ael) if (!aaz || !ael)
return; return -1;
printf("aaz: '%s' ael: '%s'\n", aaz, ael); printf("aaz: '%s' ael: '%s'\n", aaz, ael);
...@@ -127,55 +84,17 @@ void handle_cmd(struct cmd_client *cmd) ...@@ -127,55 +84,17 @@ void handle_cmd(struct cmd_client *cmd)
printf("%g %g\n", sp_az, sp_el); printf("%g %g\n", sp_az, sp_el);
go = 1; go = 1;
}
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; return 0;
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 < 0 && errno == EAGAIN) {
/* nothing */
} else {
(*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)->buflen = 0;
}
if ((*cmdp)->buflen >= 100)
(*cmdp)->buflen = 0;
}
} while (ret > 0);
}
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct setpoint_command *sp_command_az = NULL; struct setpoint_command *sp_command_az = NULL;
struct setpoint_command *sp_command_el = NULL; struct setpoint_command *sp_command_el = NULL;
struct command_server *cmd_srv;
time_t lastt = 0; time_t lastt = 0;
int fd_cmd;
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
...@@ -201,11 +120,12 @@ int main(int argc, char **argv) ...@@ -201,11 +120,12 @@ int main(int argc, char **argv)
} while (!sp_command_el); } while (!sp_command_el);
fd_cmd = tcp_listen(cmd_port, 0, 100);
if (fd_cmd < 0) { cmd_srv = command_server_create(cmd_port, 0, 100);
printf("Could not open liste port for commands\n"); if (!cmd_srv) {
printf("Could not open listen port for commands\n");
} else { } else {
ioctl(fd_cmd, FIONBIO, &(int){ 1 }); command_server_handler_raw_set(cmd_srv, handle_cmd);
} }
while (1) while (1)
...@@ -234,24 +154,14 @@ int main(int argc, char **argv) ...@@ -234,24 +154,14 @@ int main(int argc, char **argv)
FD_ZERO(&fdset_rx); FD_ZERO(&fdset_rx);
if (fd_cmd >= 0) { command_server_fdset_add(cmd_srv, &fdset_rx, &high);
FD_SET(fd_cmd, &fdset_rx);
if (fd_cmd >= high)
high = fd_cmd + 1;
}
fdset_cmd_clients(&fdset_rx, &high);
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
select(high, &fdset_rx, NULL, NULL, &tv); select(high, &fdset_rx, NULL, NULL, &tv);
if (FD_ISSET(fd_cmd, &fdset_rx)) { command_server_fdset_handle(cmd_srv, &fdset_rx);
new_cmd_client(fd_cmd);
}
check_cmd_clients(&fdset_rx);
} }
} }
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#include "dt_port_numbers.h" #include "dt_port_numbers.h"
#include "command_server.h"
int stat_port = CONSOLE_DT_MODEL_STAT_PORT; int stat_port = CONSOLE_DT_MODEL_STAT_PORT;
int cmd_port = CONSOLE_DT_MODEL_CMD_PORT; int cmd_port = CONSOLE_DT_MODEL_CMD_PORT;
...@@ -149,14 +151,6 @@ struct stat_client { ...@@ -149,14 +151,6 @@ struct stat_client {
struct stat_client *stat_clients = NULL; 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;
...@@ -181,96 +175,17 @@ void new_stat_client(int fd_stat) ...@@ -181,96 +175,17 @@ void new_stat_client(int fd_stat)
stat_clients = new_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)
{
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;
}
}
void handle_cmd(struct cmd_client *cmd) static int handle_cmd(char *name, char *val)
{ {
char *switches, *ptr;
switches = cmd->buffer;
printf("command: %s\n", switches);
if (switches) {
char *name, *val;
name = strtok_r(switches, ",=", &ptr);
val = strtok_r(NULL, ",=", &ptr);
printf("name %s value %s\n", name, val); printf("name %s value %s\n", name, val);
if (!strcmp(name, "reload")) if (!strcmp(name, "reload"))
load_ini(); load_ini();
}
}
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; return 0;
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) void output(void)
{ {
static time_t last = 0; static time_t last = 0;
...@@ -316,7 +231,8 @@ void output(void) ...@@ -316,7 +231,8 @@ void output(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int fd_stat, fd_cmd; int fd_stat;
struct command_server *cmd_srv;
dt_model_init_server(); dt_model_init_server();
...@@ -324,12 +240,13 @@ int main(int argc, char **argv) ...@@ -324,12 +240,13 @@ int main(int argc, char **argv)
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
fd_cmd = tcp_listen(cmd_port, 0, 100); cmd_srv = command_server_create(cmd_port, 0, 100);
if (fd_cmd < 0) { if (!cmd_srv) {
printf("Could not open listen port for commands\n"); printf("Could not open listen port for commands\n");
} else { } else {
ioctl(fd_cmd, FIONBIO, &(int){ 1 }); command_server_handler_set(cmd_srv, handle_cmd);
} }
fd_stat = tcp_listen(stat_port, 0, 100); fd_stat = tcp_listen(stat_port, 0, 100);
if (fd_stat < 0) { if (fd_stat < 0) {
printf("Could not open listen port for status\n"); printf("Could not open listen port for status\n");
...@@ -351,12 +268,7 @@ int main(int argc, char **argv) ...@@ -351,12 +268,7 @@ int main(int argc, char **argv)
if (fd_stat >= high) if (fd_stat >= high)
high = fd_stat + 1; high = fd_stat + 1;
} }
if (fd_cmd >= 0) { command_server_fdset_add(cmd_srv, &fdset_rx, &high);
FD_SET(fd_cmd, &fdset_rx);
if (fd_cmd >= high)
high = fd_cmd + 1;
}
fdset_cmd_clients(&fdset_rx, &high);
tv.tv_sec = OUTPUT_RATE; tv.tv_sec = OUTPUT_RATE;
tv.tv_usec = 0; tv.tv_usec = 0;
...@@ -366,10 +278,8 @@ int main(int argc, char **argv) ...@@ -366,10 +278,8 @@ int main(int argc, char **argv)
if (FD_ISSET(fd_stat, &fdset_rx)) { if (FD_ISSET(fd_stat, &fdset_rx)) {
new_stat_client(fd_stat); new_stat_client(fd_stat);
} }
if (FD_ISSET(fd_cmd, &fdset_rx)) {
new_cmd_client(fd_cmd); command_server_fdset_handle(cmd_srv, &fdset_rx);
}
check_cmd_clients(&fdset_rx);
output(); output();
} }
......
...@@ -50,8 +50,8 @@ ...@@ -50,8 +50,8 @@
#include "weather.h" #include "weather.h"
#include "dt_model.h" #include "dt_model.h"
#include "trace.h" #include "trace.h"
#include "dt_port_numbers.h" #include "dt_port_numbers.h"
#include "command_server.h"