From: Olivier Matz Date: Fri, 18 Mar 2011 09:06:52 +0000 (+0100) Subject: event_server: add an example that uses libevent X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=1c84aafee969908b17be56daeb96682a654ddebf;p=libcmdline.git event_server: add an example that uses libevent Signed-off-by: Olivier Matz --- diff --git a/Makefile b/Makefile index e6c79fd..45a51f8 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ SUBDIRS += extension_example SUBDIRS += calculator_standalone SUBDIRS += calculator_server SUBDIRS += client +SUBDIRS += event_server SUBDIRS += genconf # configuration for lib, not adviced to modify it except for diff --git a/src/event_server/commands.c b/src/event_server/commands.c new file mode 100644 index 0000000..93c11d6 --- /dev/null +++ b/src/event_server/commands.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009, Olivier MATZ + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + +/**********************************************************/ +/* operations on float */ + +/* this structure is filled when cmd_float is parsed successfully */ +struct cmd_float_result { + float a; + cmdline_fixed_string_t op; + float b; +}; + +/* function called when cmd_float is parsed successfully */ +static void cmd_float_parsed(void *parsed_result, struct cmdline *cl, void *data) +{ + struct cmd_float_result *cmd = (struct cmd_float_result *) parsed_result; + float res=0.; + + switch(cmd->op[0]) { + case '+': res = cmd->a + cmd->b; break; + case '-': res = cmd->a - cmd->b; break; + case '*': res = cmd->a * cmd->b; break; + case '/': res = cmd->a / cmd->b; break; + default: break; + } + cmdline_printf(cl, "%f\n", res); +} + +cmdline_parse_token_num_t cmd_float_a = TOKEN_NUM_INITIALIZER(struct cmd_float_result, a, FLOAT); +cmdline_parse_token_string_t cmd_float_op = TOKEN_STRING_INITIALIZER(struct cmd_float_result, op, "+#-#*#/"); +cmdline_parse_token_num_t cmd_float_b = TOKEN_NUM_INITIALIZER(struct cmd_float_result, b, FLOAT); + +cmdline_parse_inst_t cmd_float = { + .f = cmd_float_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "Operation on float (ex: '2 + 5.4')", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_float_a, + (void *)&cmd_float_op, + (void *)&cmd_float_b, + NULL, + }, +}; + + +/**********************************************************/ +/* operations trigo */ + +/* this structure is filled when cmd_trigo is parsed successfully */ +struct cmd_trigo_result { + cmdline_fixed_string_t op; + float a; +}; + +/* function called when cmd_trigo is parsed successfully */ +static void cmd_trigo_parsed(void *parsed_result, struct cmdline *cl, void *data) +{ + struct cmd_trigo_result *cmd = (struct cmd_trigo_result *) parsed_result; + float res=0.; + + if (!strcmp(cmd->op, "sin")) { + res = sin(cmd->a); + } + + else if (!strcmp(cmd->op, "cos")) { + res = cos(cmd->a); + } + + else if (!strcmp(cmd->op, "tan")) { + res = tan(cmd->a); + } + + cmdline_printf(cl, "%f\n", res); +} + +cmdline_parse_token_string_t cmd_trigo_op = TOKEN_STRING_INITIALIZER(struct cmd_trigo_result, op, "sin#tan#cos"); +cmdline_parse_token_num_t cmd_trigo_a = TOKEN_NUM_INITIALIZER(struct cmd_trigo_result, a, FLOAT); + +cmdline_parse_inst_t cmd_trigo = { + .f = cmd_trigo_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "Trigonometric operations (ex: 'sin 2.03')", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_trigo_op, + (void *)&cmd_trigo_a, + NULL, + }, +}; + + +/**********************************************************/ +/* Help */ + +/* this structure is filled when cmd_help is parsed successfully */ +struct cmd_help_result { + cmdline_fixed_string_t arg0; +}; + +/* function called when cmd_help is parsed successfully */ +static void cmd_help_parsed(void *parsed_result, struct cmdline *cl, void *data) +{ + cmdline_printf(cl, "== Simple calculator program ==\n" + "You can do simple operations on floats, like '1 + 3'\n" + "or '4.4 * 2.' (space is important).\n" + "Some trigonometric operations are available, like\n" + "'sin 4.5'.\n"); +} + +cmdline_parse_token_string_t cmd_help_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_help_result, arg0, "help"); + +cmdline_parse_inst_t cmd_help = { + .f = cmd_help_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "Display help", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_help_arg0, + NULL, + }, +}; + + + + +/**********************************************************/ +/**********************************************************/ +/****** CONTEXT (list of instruction) */ + +/* in progmem */ +cmdline_parse_ctx_t main_ctx = { + .name = "main", + .insts = { + &cmd_float, + &cmd_trigo, + &cmd_help, + NULL, + }, +}; + diff --git a/src/event_server/main.c b/src/event_server/main.c new file mode 100644 index 0000000..289bd71 --- /dev/null +++ b/src/event_server/main.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011, Olivier MATZ + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern cmdline_parse_ctx_t main_ctx[]; + +/*** main */ + +static void +evt_server_input(int s, short event, void *arg) +{ + struct cmdline *cl = arg; + struct event *evt = cl->opaque; + char buf[2048]; + int n; + + n = read(s, buf, sizeof(buf)); + if (n < 0) { + event_del(evt); + free(evt); + cmdline_free(cl); + return; + } + + if (cmdline_in(cl, buf, n) < 0) { + event_del(evt); + free(evt); + cmdline_free(cl); + return; + } +} + +static void +evt_server_new_connection(int s, short event, void *arg) +{ + struct cmdline *cl; + struct event *evt; + + /* create a new cmdline instance for this connection */ + cl = cmdline_accept(main_ctx, "example> ", s); + + /* allocate a new event for this incomming connection */ + evt = malloc(sizeof(struct event)); + if (evt == NULL) { + cmdline_free(cl); + return; + } + + cl->opaque = evt; + event_set(evt, cl->s_in, EV_READ | EV_PERSIST, evt_server_input, cl); + event_add(evt, NULL); +} + + +int main(void) +{ + struct event listen_evt; + int s; + + printf("Listening on port 1234\n"); + + /* initializa libevent */ + event_init(); + + /* open a tcp server on port 1234 */ + s = cmdline_tcpv4_listen(INADDR_ANY, 1234); + event_set(&listen_evt, s, EV_READ | EV_PERSIST, + evt_server_new_connection, NULL); + event_add(&listen_evt, NULL); + + /* libevent main loop */ + event_dispatch(); + + return 0; +} + +