From ec9bc428d40430bf421ecee2d4d34073fe060ffd Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Fri, 11 Apr 2014 16:02:30 +0930 Subject: [PATCH] Move console reading from vomp_console.c to console.c --- console.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ console.h | 25 ++++++++++ sourcefiles.mk | 1 + vomp_console.c | 111 +++++++------------------------------------- 4 files changed, 165 insertions(+), 94 deletions(-) create mode 100644 console.c create mode 100644 console.h diff --git a/console.c b/console.c new file mode 100644 index 00000000..f2292e3e --- /dev/null +++ b/console.c @@ -0,0 +1,122 @@ +/* + Copyright (C) 2014 Serval Project Inc. + + 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 2 + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "fdqueue.h" +#include "str.h" +#include "cli.h" +#include "net.h" +#include "mem.h" +#include "console.h" + +struct command_state{ + struct sched_ent alarm; + char line_buff[1024]; + size_t line_pos; + struct cli_schema *cli_commands; +}; + +struct profile_total stdin_profile={ + .name="command_handler", +}; + +static void process_command(char *line, struct cli_schema *cli_commands){ + char *argv[16]; + int argc = parse_argv(line, ' ', argv, 16); + + struct cli_parsed parsed; + switch (cli_parse(argc, (const char *const*)argv, cli_commands, &parsed)) { + case 0: + cli_invoke(&parsed, NULL); + break; + case 1: + printf("Unknown command, try help\n"); + fflush(stdout); + break; + case 2: + printf("Ambiguous command, try help\n"); + fflush(stdout); + break; + default: + printf("Error\n"); + fflush(stdout); + break; + } +} + +static void read_lines(struct sched_ent *alarm){ + struct command_state *state=(struct command_state *)alarm; + set_nonblock(alarm->poll.fd); + ssize_t bytes = read(alarm->poll.fd, state->line_buff + state->line_pos, sizeof(state->line_buff) - state->line_pos); + if (bytes<=0){ + // EOF? + unwatch(alarm); + alarm->poll.fd=-1; + return; + } + set_block(alarm->poll.fd); + size_t i = state->line_pos; + size_t processed=0; + state->line_pos+=bytes; + char *line_start=state->line_buff; + + for (;iline_pos;i++){ + if (state->line_buff[i]=='\n'){ + state->line_buff[i]=0; + if (*line_start) + process_command(line_start, state->cli_commands); + processed=i+1; + line_start = state->line_buff + processed; + } + } + + if (processed){ + // squash unprocessed data back to the start of the buffer + state->line_pos -= processed; + bcopy(state->line_buff, line_start, state->line_pos); + } +} + +struct command_state *command_register(struct cli_schema *commands, int fd){ + struct command_state *ret = emalloc_zero(sizeof(struct command_state)); + if (!ret) + return NULL; + ret->alarm.poll.fd=fd; + ret->alarm.poll.events=POLLIN; + ret->alarm.function=read_lines; + ret->alarm.stats=&stdin_profile; + ret->cli_commands = commands; + watch(&ret->alarm); + return ret; +} + +uint8_t is_command_closed(struct command_state *state){ + return state->alarm.poll.fd==-1; +} + +void command_close(struct command_state *state){ + if (is_watching(&state->alarm)) + unwatch(&state->alarm); + state->alarm.poll.fd=-1; +} + +void command_free(struct command_state *state){ + command_close(state); + free(state); +} diff --git a/console.h b/console.h new file mode 100644 index 00000000..24ebb4c2 --- /dev/null +++ b/console.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2014 Serval Project Inc. + + 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 2 + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +struct command_state; +struct command_state *command_register(struct cli_schema *commands, int fd); +uint8_t is_command_closed(struct command_state *state); +void command_close(struct command_state *state); +void command_free(struct command_state *state); + + diff --git a/sourcefiles.mk b/sourcefiles.mk index c12ca1b4..37aba602 100644 --- a/sourcefiles.mk +++ b/sourcefiles.mk @@ -35,6 +35,7 @@ SQLITE3_SOURCES = \ SERVAL_DAEMON_SOURCES = \ cli.c \ commandline.c \ + console.c \ crypto.c \ directory_client.c \ dna_helper.c \ diff --git a/vomp_console.c b/vomp_console.c index 6b625426..950c2eb8 100644 --- a/vomp_console.c +++ b/vomp_console.c @@ -56,6 +56,7 @@ #endif #include "serval.h" +#include "console.h" #include "conf.h" #include "cli.h" #include "monitor-client.h" @@ -64,14 +65,12 @@ #include "strbuf.h" #include "strbuf_helpers.h" -static void read_lines(struct sched_ent *alarm); static int console_dial(const struct cli_parsed *parsed, struct cli_context *context); static int console_answer(const struct cli_parsed *parsed, struct cli_context *context); static int console_hangup(const struct cli_parsed *parsed, struct cli_context *context); static int console_audio(const struct cli_parsed *parsed, struct cli_context *context); static int console_usage(const struct cli_parsed *parsed, struct cli_context *context); static int console_quit(const struct cli_parsed *parsed, struct cli_context *context); -static void console_command(char *line); static void monitor_read(struct sched_ent *alarm); struct cli_schema console_commands[]={ @@ -84,26 +83,6 @@ struct cli_schema console_commands[]={ {NULL, {NULL, NULL, NULL}, 0, NULL}, }; -struct line_state{ - struct sched_ent alarm; - int fd; - char line_buff[1024]; - int line_pos; - void (*process_line)(char *line); -}; - -struct profile_total stdin_profile={ - .name="read_lines", -}; -struct line_state stdin_state={ - .alarm = { - .poll = {.fd = STDIN_FILENO,.events = POLLIN}, - .function = read_lines, - .stats=&stdin_profile - }, - .fd=0, - .process_line=console_command, -}; struct profile_total monitor_profile={ .name="monitor_read", }; @@ -122,6 +101,7 @@ struct call{ struct call *calls=NULL; struct monitor_state *monitor_state; +struct command_state *stdin_state; static void send_hangup(int session_id){ monitor_client_writeline(monitor_alarm.poll.fd, "hangup %06x\n",session_id); @@ -331,13 +311,7 @@ static int console_hangup(const struct cli_parsed *UNUSED(parsed), struct cli_co static int console_quit(const struct cli_parsed *UNUSED(parsed), struct cli_context *UNUSED(context)) { - if (monitor_alarm.poll.fd!=-1){ - printf("Shutting down\n"); - fflush(stdout); - unwatch(&monitor_alarm); - monitor_client_close(monitor_alarm.poll.fd, monitor_state); - monitor_alarm.poll.fd=-1; - } + command_close(stdin_state); return 0; } @@ -372,66 +346,6 @@ static int console_usage(const struct cli_parsed *UNUSED(parsed), struct cli_con return 0; } -static void console_command(char *line){ - char *argv[16]; - int argc = parse_argv(line, ' ', argv, 16); - - struct cli_parsed parsed; - switch (cli_parse(argc, (const char *const*)argv, console_commands, &parsed)) { - case 0: - cli_invoke(&parsed, NULL); - break; - case 1: - printf("Unknown command, try help\n"); - fflush(stdout); - break; - case 2: - printf("Ambiguous command, try help\n"); - fflush(stdout); - break; - default: - printf("Error\n"); - fflush(stdout); - break; - } -} - -static void read_lines(struct sched_ent *alarm){ - struct line_state *state=(struct line_state *)alarm; - set_nonblock(STDIN_FILENO); - int bytes = read(state->alarm.poll.fd, state->line_buff + state->line_pos, sizeof(state->line_buff) - state->line_pos); - if (bytes<=0){ - if (monitor_alarm.poll.fd!=-1){ - unwatch(&monitor_alarm); - monitor_client_close(monitor_alarm.poll.fd, monitor_state); - monitor_alarm.poll.fd=-1; - } - return; - } - - set_block(STDIN_FILENO); - int i = state->line_pos; - int processed=0; - state->line_pos+=bytes; - char *line_start=state->line_buff; - - for (;iline_pos;i++){ - if (state->line_buff[i]=='\n'){ - state->line_buff[i]=0; - if (*line_start) - state->process_line(line_start); - processed=i+1; - line_start = state->line_buff + processed; - } - } - - if (processed){ - // squash unprocessed data back to the start of the buffer - state->line_pos -= processed; - bcopy(state->line_buff, line_start, state->line_pos); - } -} - static void monitor_read(struct sched_ent *alarm){ if (monitor_client_read(alarm->poll.fd, monitor_state, console_handlers, sizeof(console_handlers)/sizeof(struct monitor_command_handler))<0){ @@ -449,6 +363,8 @@ int app_vomp_console(const struct cli_parsed *parsed, struct cli_context *UNUSED DEBUG_cli_parsed(parsed); monitor_alarm.poll.fd = monitor_client_open(&monitor_state); + if (monitor_alarm.poll.fd==-1) + return -1; monitor_client_writeline(monitor_alarm.poll.fd, "monitor vomp %d\n", VOMP_CODEC_TEXT); @@ -456,13 +372,20 @@ int app_vomp_console(const struct cli_parsed *parsed, struct cli_context *UNUSED set_nonblock(monitor_alarm.poll.fd); watch(&monitor_alarm); - watch(&stdin_state.alarm); + stdin_state = command_register(console_commands, STDIN_FILENO); - while(monitor_alarm.poll.fd!=-1){ - fd_poll(); + while(monitor_alarm.poll.fd!=-1 && !is_command_closed(stdin_state) && fd_poll()) + ; + + printf("Shutting down\n"); + fflush(stdout); + + command_free(stdin_state); + if (monitor_alarm.poll.fd!=-1){ + unwatch(&monitor_alarm); + monitor_client_close(monitor_alarm.poll.fd, monitor_state); + monitor_alarm.poll.fd=-1; } - unwatch(&stdin_state.alarm); - return 0; }