event_server: add an example that uses libevent
authorOlivier Matz <zer0@droids-corp.org>
Fri, 18 Mar 2011 09:06:52 +0000 (10:06 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Fri, 18 Mar 2011 09:06:52 +0000 (10:06 +0100)
Signed-off-by: Olivier Matz <zer0@droids-corp.org>
Makefile
src/event_server/commands.c [new file with mode: 0644]
src/event_server/main.c [new file with mode: 0644]

index e6c79fd..45a51f8 100644 (file)
--- 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 (file)
index 0000000..93c11d6
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
+ * 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 <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include <netinet/in.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline.h>
+
+
+
+/**********************************************************/
+/* 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 (file)
index 0000000..289bd71
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, Olivier MATZ <zer0@droids-corp.org>
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <termios.h>
+#include <netinet/in.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include <event.h>
+
+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;
+}
+
+