examples: add getopt argument parsing for client and server
authorOlivier Matz <zer0@droids-corp.org>
Sun, 31 Jul 2011 19:48:13 +0000 (21:48 +0200)
committerOlivier Matz <zer0@droids-corp.org>
Sun, 31 Jul 2011 19:48:13 +0000 (21:48 +0200)
Signed-off-by: Olivier Matz <zer0@droids-corp.org>
src/calculator_server/main.c
src/client/main.c
src/event_server/main.c

index 0406a06..d3c5e05 100644 (file)
 #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 <arpa/inet.h>
+
+#include <getopt.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
 
 extern cmdline_parse_ctx_t main_ctx[];
 
-struct cmdline *cl;
+static struct sockaddr addr;
+static uint16_t port = 1234;
+
+static void
+usage(const char *prgname)
+{
+       printf("%s [-a ADDRESS] [-p PORT]\n"
+              "\n"
+              "Start a command line server on a TCP listen socket. Only\n"
+              "one connection is accepted, then the program exits.\n"
+              "The default behaviour is to listen on 0.0.0.0:1234\n"
+              "\n"
+              "  -a ADDR:  IPv4 or IPv6 local address to listen on (default\n"
+              "            is 0.0.0.0).\n"
+              "  -p PORT:  port to listen on (default is 1234).\n",
+              prgname);
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+parse_args(int argc, char **argv)
+{
+       int opt, ret;
+       char **argvopt;
+       int option_index;
+       char *prgname = argv[0];
+       char *end = NULL;
+       static struct option lgopts[] = {
+               {0, 0, 0, 0}
+       };
+
+       argvopt = argv;
+
+       while ((opt = getopt_long(argc, argvopt, "a:p:",
+                                 lgopts, &option_index)) != EOF) {
+
+               switch (opt) {
+
+               case 'a':
+                       if (strchr(optarg, '.') != NULL) {
+                               struct sockaddr_in *sin =
+                                       (struct sockaddr_in *)&addr;
+                               addr.sa_family = AF_INET;
+                               ret = inet_pton(AF_INET, optarg,
+                                               &sin->sin_addr);
+                       }
+                       else {
+                               struct sockaddr_in6 *sin6 =
+                                       (struct sockaddr_in6 *)&addr;
+                               addr.sa_family = AF_INET6;
+                               ret = inet_pton(AF_INET6, optarg,
+                                               &sin6->sin6_addr);
+                       }
+
+                       if (ret != 1) {
+                               printf("Bad address\n");
+                               usage(prgname);
+                               return -1;
+                       }
+                       break;
 
-int main(void)
+               case 'p':
+                       port = strtoul(optarg, &end, 0);
+                       if ((optarg[0] == '\0') ||
+                           (end == NULL) ||
+                           (*end != '\0')) {
+                               printf("Invalid port\n");
+                               usage(prgname);
+                               return -1;
+                       }
+
+                       break;
+
+               /* long options */
+               case 0:
+                       /* if (!strcmp(lgopts[option_index].name, "option")) */
+                       break;
+
+               default:
+                       usage(prgname);
+                       return -1;
+               }
+       }
+
+       if (argc != optind) {
+               printf("Invalid argument\n");
+               usage(prgname);
+               return -1;
+       }
+
+       ret = optind-1;
+
+       return ret;
+}
+
+int main(int argc, char **argv)
 {
+       struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+       struct cmdline *cl;
        int s;
-       s = cmdline_tcpv4_listen(INADDR_ANY, 1234);
+
+       if (parse_args(argc, argv) < 0)
+               exit(1);
+
+       printf("Listening on port %d\n", port);
+
+       /* open a tcp server on specified port */
+       if (addr.sa_family == AF_INET)
+               s = cmdline_tcpv4_listen(sin->sin_addr.s_addr, port);
+       else
+               s = cmdline_tcpv6_listen(sin6->sin6_addr, port);
+
        cl = cmdline_accept(main_ctx, "example> ", s);
-       if (cl == NULL)
+       if (cl == NULL) {
+               printf("accept() failed\n");
                return 1;
+       }
        cmdline_interact(cl);
        cmdline_free(cl);
        return 0;
index 5f177d2..c0d6079 100644 (file)
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
-#include <math.h>
+#include <getopt.h>
 
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <unistd.h>
 #include <termios.h>
 
+static struct sockaddr addr;
+static uint16_t port = 1234;
 
-int main(void) 
+static void
+usage(const char *prgname)
 {
+       printf("%s [-a ADDRESS] [-p PORT]\n"
+              "\n"
+              "Start a client to connect to a command line server, using\n"
+              "a TCP socket.\n"
+              "The default behaviour is to connect to 127.0.0.1:1234\n"
+              "\n"
+              "  -a ADDR:  IPv4 or IPv6 local address to listen on (default\n"
+              "            is 127.0.0.1).\n"
+              "  -p PORT:  port to connect to (default is 1234).\n",
+              prgname);
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+parse_args(int argc, char **argv)
+{
+       int opt, ret;
+       char **argvopt;
+       int option_index;
+       char *prgname = argv[0];
+       char *end = NULL;
+       static struct option lgopts[] = {
+               {0, 0, 0, 0}
+       };
+
+       argvopt = argv;
+
+       while ((opt = getopt_long(argc, argvopt, "a:p:",
+                                 lgopts, &option_index)) != EOF) {
+
+               switch (opt) {
+
+               case 'a':
+                       if (strchr(optarg, '.') != NULL) {
+                               struct sockaddr_in *sin =
+                                       (struct sockaddr_in *)&addr;
+                               addr.sa_family = AF_INET;
+                               ret = inet_pton(AF_INET, optarg,
+                                               &sin->sin_addr);
+                       }
+                       else {
+                               struct sockaddr_in6 *sin6 =
+                                       (struct sockaddr_in6 *)&addr;
+                               addr.sa_family = AF_INET6;
+                               ret = inet_pton(AF_INET6, optarg,
+                                               &sin6->sin6_addr);
+                       }
+
+                       if (ret != 1) {
+                               printf("Bad address\n");
+                               usage(prgname);
+                               return -1;
+                       }
+                       break;
+
+               case 'p':
+                       port = strtoul(optarg, &end, 0);
+                       if ((optarg[0] == '\0') ||
+                           (end == NULL) ||
+                           (*end != '\0')) {
+                               printf("Invalid port\n");
+                               usage(prgname);
+                               return -1;
+                       }
+
+                       break;
+
+               /* long options */
+               case 0:
+                       /* if (!strcmp(lgopts[option_index].name, "option")) */
+                       break;
+
+               default:
+                       usage(prgname);
+                       return -1;
+               }
+       }
+
+       if (argc != optind) {
+               printf("Invalid argument\n");
+               usage(prgname);
+               return -1;
+       }
+
+       ret = optind-1;
+
+       return ret;
+}
+
+int main(int argc, char **argv)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
        struct termios oldterm, term;
-       struct sockaddr_in sin_ci;
        fd_set fds;
        int s;
        char c;
+       char buf[INET6_ADDRSTRLEN];
+
+       /* default */
+       sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       sin->sin_family = AF_INET;
+
+       if (parse_args(argc, argv) < 0)
+               exit(1);
 
        s = socket(PF_INET, SOCK_STREAM, 0);
        if (s < 0) {
@@ -53,18 +157,33 @@ int main(void)
                return s;
        }
 
-       /* XXX specify address */
-       memset(&sin_ci, 0, sizeof(sin_ci));
-       sin_ci.sin_family = AF_INET;
-       inet_pton(AF_INET, "127.0.0.1", &sin_ci.sin_addr.s_addr);
-       sin_ci.sin_port = htons(1234);
+       switch (addr.sa_family) {
+               case AF_INET:
+                       sin->sin_port = htons(port);
 #ifndef __linux__
-       sin_ci.sin_len = sizeof(sin_ci);
+                       sin->sin_len = sizeof(*sin);
 #endif
+                       printf("Connecting to %s:%d\n",
+                              inet_ntop(AF_INET, &sin->sin_addr, buf,
+                                        sizeof(*sin)), port);
+                       break;
+               case AF_INET6:
+                       sin6->sin6_port = htons(port);
+#ifndef __linux__
+                       sin6->sin6_len = sizeof(*sin6);
+#endif
+                       printf("Connecting to %s:%d\n",
+                              inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
+                                        sizeof(*sin6)), port);
+                       break;
+               default:
+                       printf("bad address\n");
+                       return -1;
+       }
 
-       if (connect(s, (struct sockaddr *)&sin_ci, sizeof(sin_ci)) < 0) {
+       if (connect(s, &addr, sizeof(addr)) < 0) {
                printf("connect() failed\n");
-               return s;
+               return -1;
        }
 
        tcgetattr(0, &oldterm);
@@ -95,5 +214,3 @@ int main(void)
 
        return 0;
 }
-
-
index 289bd71..eb88dbb 100644 (file)
 #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 <arpa/inet.h>
+
+#include <getopt.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
 
 #include <event.h>
 
-extern cmdline_parse_ctx_t main_ctx[];
+static struct sockaddr addr;
+static uint16_t port = 1234;
 
-/*** main */
+extern cmdline_parse_ctx_t main_ctx[];
 
 static void
 evt_server_input(int s, short event, void *arg)
@@ -95,19 +96,118 @@ evt_server_new_connection(int s, short event, void *arg)
        event_add(evt, NULL);
 }
 
+static void
+usage(const char *prgname)
+{
+       printf("%s [-a ADDRESS] [-p PORT]\n"
+              "\n"
+              "Start a command line server on a TCP listen socket. This example\n"
+              "uses the libevent to support several simultaneous connections.\n"
+              "The default behaviour is to listen on 0.0.0.0:1234\n"
+              "\n"
+              "  -a ADDR:  IPv4 or IPv6 local address to listen on (default\n"
+              "            is 0.0.0.0).\n"
+              "  -p PORT:  port to listen on (default is 1234).\n",
+              prgname);
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+parse_args(int argc, char **argv)
+{
+       int opt, ret;
+       char **argvopt;
+       int option_index;
+       char *prgname = argv[0];
+       char *end = NULL;
+       static struct option lgopts[] = {
+               {0, 0, 0, 0}
+       };
+
+       argvopt = argv;
+
+       while ((opt = getopt_long(argc, argvopt, "a:p:",
+                                 lgopts, &option_index)) != EOF) {
+
+               switch (opt) {
+
+               case 'a':
+                       if (strchr(optarg, '.') != NULL) {
+                               struct sockaddr_in *sin =
+                                       (struct sockaddr_in *)&addr;
+                               addr.sa_family = AF_INET;
+                               ret = inet_pton(AF_INET, optarg,
+                                               &sin->sin_addr);
+                       }
+                       else {
+                               struct sockaddr_in6 *sin6 =
+                                       (struct sockaddr_in6 *)&addr;
+                               addr.sa_family = AF_INET6;
+                               ret = inet_pton(AF_INET6, optarg,
+                                               &sin6->sin6_addr);
+                       }
+
+                       if (ret != 1) {
+                               printf("Bad address\n");
+                               usage(prgname);
+                               return -1;
+                       }
+                       break;
+
+               case 'p':
+                       port = strtoul(optarg, &end, 0);
+                       if ((optarg[0] == '\0') ||
+                           (end == NULL) ||
+                           (*end != '\0')) {
+                               printf("Invalid port\n");
+                               usage(prgname);
+                               return -1;
+                       }
+
+                       break;
+
+               /* long options */
+               case 0:
+                       /* if (!strcmp(lgopts[option_index].name, "option")) */
+                       break;
+
+               default:
+                       usage(prgname);
+                       return -1;
+               }
+       }
+
+       if (argc != optind) {
+               printf("Invalid argument\n");
+               usage(prgname);
+               return -1;
+       }
 
-int main(void)
+       ret = optind-1;
+
+       return ret;
+}
+
+int main(int argc, char **argv)
 {
+       struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
        struct event listen_evt;
        int s;
 
-       printf("Listening on port 1234\n");
+       if (parse_args(argc, argv) < 0)
+               exit(1);
+
+       printf("Listening on port %d\n", port);
 
        /* initializa libevent */
        event_init();
 
-       /* open a tcp server on port 1234 */
-       s = cmdline_tcpv4_listen(INADDR_ANY, 1234);
+       /* open a tcp server on specified port */
+       if (addr.sa_family == AF_INET)
+               s = cmdline_tcpv4_listen(sin->sin_addr.s_addr, port);
+       else
+               s = cmdline_tcpv6_listen(sin6->sin6_addr, port);
        event_set(&listen_evt, s, EV_READ | EV_PERSIST,
                  evt_server_new_connection, NULL);
        event_add(&listen_evt, NULL);
@@ -117,5 +217,3 @@ int main(void)
 
        return 0;
 }
-
-