Signed-off-by: Angus Salkeld asalkeld@redhat.com --- Makefile.am | 2 +- configure.ac | 1 + examples/.gitignore | 1 + examples/Makefile.am | 28 ++++++ examples/simplelog.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/.gitignore | 1 - tests/Makefile.am | 7 +-- tests/simple-log.c | 224 -------------------------------------------------- 8 files changed, 256 insertions(+), 232 deletions(-) create mode 100644 examples/.gitignore create mode 100644 examples/Makefile.am create mode 100644 examples/simplelog.c delete mode 100644 tests/simple-log.c
diff --git a/Makefile.am b/Makefile.am index a64a7fc..09aa451 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,7 +41,7 @@ ACLOCAL_AMFLAGS = -I m4
dist_doc_DATA = COPYING INSTALL README.markdown
-SUBDIRS = include lib docs tests +SUBDIRS = include lib docs tests examples
doxygen: $(MAKE) -C docs doxygen diff --git a/configure.ac b/configure.ac index c425e94..c8dcd2c 100644 --- a/configure.ac +++ b/configure.ac @@ -450,6 +450,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile lib/libqb.pc tests/Makefile + examples/Makefile docs/Makefile docs/man.dox docs/html.dox]) diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..097ac67 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +simplelog diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..2b7cad8 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,28 @@ +# Copyright (c) 2011 Red Hat, Inc. +# +# Authors: Angus Salkeld asalkeld@redhat.com +# +# This file is part of libqb. +# +# libqb is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2.1 of the License, or +# (at your option) any later version. +# +# libqb 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with libqb. If not, see http://www.gnu.org/licenses/. +# +MAINTAINERCLEANFILES = Makefiles.in +EXTRA_DIST = +CLEANFILES = + +noinst_PROGRAMS = simplelog + +simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h +simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +simplelog_LDADD = -lrt $(top_builddir)/lib/libqb.la diff --git a/examples/simplelog.c b/examples/simplelog.c new file mode 100644 index 0000000..ef57503 --- /dev/null +++ b/examples/simplelog.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" +#include <signal.h> +#include <syslog.h> + +#include <qb/qbdefs.h> +#include <qb/qblog.h> + +#define MY_TAG_ONE (1) +#define MY_TAG_TWO (1 << 1) +#define MY_TAG_THREE (1 << 2) + +static void func_one(void) +{ + FILE* fd; + + qb_enter(); + qb_logt(LOG_DEBUG, MY_TAG_TWO, "arf arf?"); + qb_logt(LOG_CRIT, MY_TAG_THREE, "arrrg!"); + qb_logt(134, MY_TAG_THREE, "big priority"); + qb_logt(LOG_ERR, MY_TAG_THREE, "oops, I did it again"); + qb_log(LOG_INFO, "are you aware ..."); + + fd = fopen("/nothing.txt", "r+"); + if (fd == NULL) { + qb_perror(LOG_ERR, "can't open("/nothing.txt")"); + } else { + fclose(fd); + } + qb_leave(); +} + +static void func_two(void) +{ + qb_enter(); + qb_logt(LOG_DEBUG, 0, "arf arf?"); + qb_logt(LOG_CRIT, MY_TAG_ONE, "arrrg!"); + qb_log(LOG_ERR, "oops, I did it again"); + qb_logt(LOG_INFO, MY_TAG_THREE, "are you aware ..."); + qb_leave(); +} + +static void show_usage(const char *name) +{ + printf("usage: \n"); + printf("%s <options>\n", name); + printf("\n"); + printf(" options:\n"); + printf("\n"); + printf(" -v verbose\n"); + printf(" -t threaded logging\n"); + printf(" -e log to stderr\n"); + printf(" -b log to blackbox\n"); + printf(" -f <filename> log to a file\n"); + printf(" -h show this help text\n"); + printf("\n"); +} + +static int32_t do_blackbox = QB_FALSE; +static int32_t do_threaded = QB_FALSE; + +static void sigsegv_handler(int sig) +{ + (void)signal (SIGSEGV, SIG_DFL); + qb_log_fini(); + if (do_blackbox) { + qb_log_blackbox_write_to_file("simple-log.fdata"); + } + raise(SIGSEGV); +} + +static const char *my_tags_stringify(uint32_t tags) +{ + if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT)) { + return "libqb"; + } else if (qb_bit_is_set(tags, 0)) { + return "ONE"; + } else if (qb_bit_is_set(tags, 1)) { + return "TWO"; + } else if (qb_bit_is_set(tags, 2)) { + return "THREE"; + } else { + return "MAIN"; + } +} + +static void +trace_logger(int32_t t, + struct qb_log_callsite *cs, + time_t timestamp, + const char *msg) +{ + char output_buffer[QB_LOG_MAX_LEN]; + qb_log_target_format(t, cs, timestamp, msg, output_buffer); + fprintf(stderr, "%s\n", output_buffer); +} + +int32_t main(int32_t argc, char *argv[]) +{ + const char *options = "vhtebdf:"; + int32_t opt; + int32_t tracer; + int32_t priority = LOG_WARNING; + int32_t do_stderr = QB_FALSE; + int32_t do_dump_blackbox = QB_FALSE; + char *logfile = NULL; + int32_t log_fd = -1; + + while ((opt = getopt(argc, argv, options)) != -1) { + switch (opt) { + case 'd': + do_dump_blackbox = QB_TRUE; + break; + case 't': + do_threaded = QB_TRUE; + break; + case 'e': + do_stderr = QB_TRUE; + break; + case 'b': + do_blackbox = QB_TRUE; + break; + case 'f': + logfile = optarg; + break; + case 'v': + priority++; + break; + case 'h': + default: + show_usage(argv[0]); + exit(0); + break; + } + } + + if (do_dump_blackbox) { + qb_log_blackbox_print_from_file("simple-log.fdata"); + exit(0); + } + + signal(SIGSEGV, sigsegv_handler); + + qb_log_init("simple-log", LOG_USER, LOG_INFO); + qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded); + qb_log_tags_stringify_fn_set(my_tags_stringify); + + tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL); + + if (do_stderr) { + qb_log_filter_ctl2(QB_LOG_STDERR, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, __FILE__, + LOG_ALERT, QB_MIN(LOG_DEBUG, priority)); + qb_log_format_set(QB_LOG_STDERR, "%4g: %f:%l [%p] %b"); + qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); + + qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE); + qb_log_format_set(tracer, "%4g: %n() %b"); + qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, __FILE__, + LOG_TRACE, 200); + } + if (do_blackbox) { + qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, "*", LOG_DEBUG); + qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 4096); + qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE); + qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE); + } + if (logfile) { + log_fd = qb_log_file_open(logfile); + qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, __FILE__, priority); + qb_log_format_set(log_fd, "%t %n() [%p] %b"); + qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded); + qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE); + } + if (do_threaded) { + qb_log_thread_start(); + } + qb_log(LOG_DEBUG, "hello"); + qb_log(LOG_INFO, "this is an info"); + qb_log(LOG_NOTICE, "hello - notice?"); + func_one(); + func_two(); + + qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE); + + qb_log(LOG_WARNING, "no syslog"); + qb_log(LOG_ERR, "no syslog"); + +#if 0 + // test blackbox + logfile = NULL; + logfile[5] = 'a'; +#endif + if (do_blackbox) { + qb_log_blackbox_write_to_file("simple-log.fdata"); + qb_log_blackbox_print_from_file("simple-log.fdata"); + qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE); + } + qb_log_fini(); + return 0; +} + diff --git a/tests/.gitignore b/tests/.gitignore index aac425f..4b117ca 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -6,5 +6,4 @@ bms loop rbreader rbwriter -simple-log write_logs.c diff --git a/tests/Makefile.am b/tests/Makefile.am index a89bf26..fbe1ba0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,7 +21,7 @@ MAINTAINERCLEANFILES = Makefiles.in EXTRA_DIST = CLEANFILES =
-noinst_PROGRAMS = bmc bmcpt bms rbwriter rbreader loop simple-log bench-log +noinst_PROGRAMS = bmc bmcpt bms rbwriter rbreader loop bench-log
bmc_SOURCES = bmc.c $(top_builddir)/include/qb/qbipcc.h bmc_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include @@ -47,11 +47,6 @@ loop_SOURCES = loop.c $(top_builddir)/include/qb/qbloop.h loop_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include loop_LDADD = -lrt $(top_builddir)/lib/libqb.la
-simple_log_SOURCES = simple-log.c $(top_builddir)/include/qb/qblog.h -simple_log_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include -simple_log_LDADD = -lrt $(top_builddir)/lib/libqb.la - - if HAVE_DICT_WORDS EXTRA_DIST += make-log-test CLEANFILES += write_logs.c diff --git a/tests/simple-log.c b/tests/simple-log.c deleted file mode 100644 index ef57503..0000000 --- a/tests/simple-log.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2011 Red Hat, Inc. - * - * All rights reserved. - * - * Author: Angus Salkeld asalkeld@redhat.com - * - * libqb is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libqb 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libqb. If not, see http://www.gnu.org/licenses/. - */ -#include "os_base.h" -#include <signal.h> -#include <syslog.h> - -#include <qb/qbdefs.h> -#include <qb/qblog.h> - -#define MY_TAG_ONE (1) -#define MY_TAG_TWO (1 << 1) -#define MY_TAG_THREE (1 << 2) - -static void func_one(void) -{ - FILE* fd; - - qb_enter(); - qb_logt(LOG_DEBUG, MY_TAG_TWO, "arf arf?"); - qb_logt(LOG_CRIT, MY_TAG_THREE, "arrrg!"); - qb_logt(134, MY_TAG_THREE, "big priority"); - qb_logt(LOG_ERR, MY_TAG_THREE, "oops, I did it again"); - qb_log(LOG_INFO, "are you aware ..."); - - fd = fopen("/nothing.txt", "r+"); - if (fd == NULL) { - qb_perror(LOG_ERR, "can't open("/nothing.txt")"); - } else { - fclose(fd); - } - qb_leave(); -} - -static void func_two(void) -{ - qb_enter(); - qb_logt(LOG_DEBUG, 0, "arf arf?"); - qb_logt(LOG_CRIT, MY_TAG_ONE, "arrrg!"); - qb_log(LOG_ERR, "oops, I did it again"); - qb_logt(LOG_INFO, MY_TAG_THREE, "are you aware ..."); - qb_leave(); -} - -static void show_usage(const char *name) -{ - printf("usage: \n"); - printf("%s <options>\n", name); - printf("\n"); - printf(" options:\n"); - printf("\n"); - printf(" -v verbose\n"); - printf(" -t threaded logging\n"); - printf(" -e log to stderr\n"); - printf(" -b log to blackbox\n"); - printf(" -f <filename> log to a file\n"); - printf(" -h show this help text\n"); - printf("\n"); -} - -static int32_t do_blackbox = QB_FALSE; -static int32_t do_threaded = QB_FALSE; - -static void sigsegv_handler(int sig) -{ - (void)signal (SIGSEGV, SIG_DFL); - qb_log_fini(); - if (do_blackbox) { - qb_log_blackbox_write_to_file("simple-log.fdata"); - } - raise(SIGSEGV); -} - -static const char *my_tags_stringify(uint32_t tags) -{ - if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT)) { - return "libqb"; - } else if (qb_bit_is_set(tags, 0)) { - return "ONE"; - } else if (qb_bit_is_set(tags, 1)) { - return "TWO"; - } else if (qb_bit_is_set(tags, 2)) { - return "THREE"; - } else { - return "MAIN"; - } -} - -static void -trace_logger(int32_t t, - struct qb_log_callsite *cs, - time_t timestamp, - const char *msg) -{ - char output_buffer[QB_LOG_MAX_LEN]; - qb_log_target_format(t, cs, timestamp, msg, output_buffer); - fprintf(stderr, "%s\n", output_buffer); -} - -int32_t main(int32_t argc, char *argv[]) -{ - const char *options = "vhtebdf:"; - int32_t opt; - int32_t tracer; - int32_t priority = LOG_WARNING; - int32_t do_stderr = QB_FALSE; - int32_t do_dump_blackbox = QB_FALSE; - char *logfile = NULL; - int32_t log_fd = -1; - - while ((opt = getopt(argc, argv, options)) != -1) { - switch (opt) { - case 'd': - do_dump_blackbox = QB_TRUE; - break; - case 't': - do_threaded = QB_TRUE; - break; - case 'e': - do_stderr = QB_TRUE; - break; - case 'b': - do_blackbox = QB_TRUE; - break; - case 'f': - logfile = optarg; - break; - case 'v': - priority++; - break; - case 'h': - default: - show_usage(argv[0]); - exit(0); - break; - } - } - - if (do_dump_blackbox) { - qb_log_blackbox_print_from_file("simple-log.fdata"); - exit(0); - } - - signal(SIGSEGV, sigsegv_handler); - - qb_log_init("simple-log", LOG_USER, LOG_INFO); - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded); - qb_log_tags_stringify_fn_set(my_tags_stringify); - - tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL); - - if (do_stderr) { - qb_log_filter_ctl2(QB_LOG_STDERR, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FILE, __FILE__, - LOG_ALERT, QB_MIN(LOG_DEBUG, priority)); - qb_log_format_set(QB_LOG_STDERR, "%4g: %f:%l [%p] %b"); - qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); - - qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE); - qb_log_format_set(tracer, "%4g: %n() %b"); - qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FILE, __FILE__, - LOG_TRACE, 200); - } - if (do_blackbox) { - qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FILE, "*", LOG_DEBUG); - qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 4096); - qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE); - qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE); - } - if (logfile) { - log_fd = qb_log_file_open(logfile); - qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FILE, __FILE__, priority); - qb_log_format_set(log_fd, "%t %n() [%p] %b"); - qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded); - qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE); - } - if (do_threaded) { - qb_log_thread_start(); - } - qb_log(LOG_DEBUG, "hello"); - qb_log(LOG_INFO, "this is an info"); - qb_log(LOG_NOTICE, "hello - notice?"); - func_one(); - func_two(); - - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE); - - qb_log(LOG_WARNING, "no syslog"); - qb_log(LOG_ERR, "no syslog"); - -#if 0 - // test blackbox - logfile = NULL; - logfile[5] = 'a'; -#endif - if (do_blackbox) { - qb_log_blackbox_write_to_file("simple-log.fdata"); - qb_log_blackbox_print_from_file("simple-log.fdata"); - qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE); - } - qb_log_fini(); - return 0; -} -
Signed-off-by: Angus Salkeld asalkeld@redhat.com --- examples/.gitignore | 2 + examples/Makefile.am | 11 +++- examples/tcpclient.c | 74 ++++++++++++++++++++++++ examples/tcpserver.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 1 deletions(-) create mode 100644 examples/tcpclient.c create mode 100644 examples/tcpserver.c
diff --git a/examples/.gitignore b/examples/.gitignore index 097ac67..861a32c 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1 +1,3 @@ simplelog +tcpclient +tcpserver diff --git a/examples/Makefile.am b/examples/Makefile.am index 2b7cad8..867f9d8 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -21,8 +21,17 @@ MAINTAINERCLEANFILES = Makefiles.in EXTRA_DIST = CLEANFILES =
-noinst_PROGRAMS = simplelog +noinst_PROGRAMS = simplelog tcpclient tcpserver
simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include simplelog_LDADD = -lrt $(top_builddir)/lib/libqb.la + +tcpclient_SOURCES = tcpclient.c $(top_builddir)/include/qb/qbloop.h +tcpclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +tcpclient_LDADD = -lrt $(top_builddir)/lib/libqb.la + +tcpserver_SOURCES = tcpserver.c $(top_builddir)/include/qb/qbloop.h +tcpserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +tcpserver_LDADD = -lrt $(top_builddir)/lib/libqb.la + diff --git a/examples/tcpclient.c b/examples/tcpclient.c new file mode 100644 index 0000000..8283321 --- /dev/null +++ b/examples/tcpclient.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" +#include <netdb.h> + + +int +main(int argc, char *argv[]) +{ + int sock; + int32_t res; + char send_data[1024]; + char recv_data[1024]; + struct sockaddr_in server_addr; + struct hostent *host = gethostbyname("127.0.0.1"); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("Socket"); + exit(1); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(5000); + server_addr.sin_addr = *((struct in_addr *)host->h_addr); + bzero(&(server_addr.sin_zero),8); + + if (connect(sock, (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) { + perror("Connect"); + exit(1); + } + + while(1) { + printf("\nSEND (q or Q to quit) : "); + if (gets(send_data) == NULL) { + continue; + } + + if (strcmp(send_data , "q") != 0 && + strcmp(send_data , "Q") != 0) { + res = send(sock, send_data, strlen(send_data), 0); + } else { + send(sock,send_data, strlen(send_data), 0); + close(sock); + break; + } + + if (res > 0) { + res = recv(sock, recv_data, 1024, 0); + recv_data[res] = '\0'; + + printf("\nResponse: %s ", recv_data); + } + } + return EXIT_SUCCESS; +} diff --git a/examples/tcpserver.c b/examples/tcpserver.c new file mode 100644 index 0000000..fddaa39 --- /dev/null +++ b/examples/tcpserver.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" + +#include <netdb.h> +#include <arpa/inet.h> +#include <poll.h> + +#include <qb/qbdefs.h> +#include <qb/qbloop.h> + +static int32_t +sock_read_fn(int32_t fd, int32_t revents, void *data) +{ + char recv_data[1024]; + char send_data[1024]; + int bytes_recieved; + + if (revents & POLLHUP) { + printf("Socket %d peer closed\n", fd); + close(fd); + return QB_FALSE; + } + + bytes_recieved = recv(fd, recv_data, 1024, 0); + if (bytes_recieved < 0) { + perror("recv"); + return QB_TRUE; + } + recv_data[bytes_recieved] = '\0'; + + if (strcmp(recv_data, "q") == 0 || + strcmp(recv_data, "Q") == 0) { + printf("Quiting connection from socket %d\n", fd); + close(fd); + return QB_FALSE; + } else { + printf("Recieved: %s\n", recv_data); + snprintf(send_data, 1024, "ACK %d bytes", bytes_recieved); + send(fd, send_data, strlen(send_data), 0); + } + return QB_TRUE; +} + +static int32_t +sock_accept_fn(int32_t fd, int32_t revents, void *data) +{ + struct sockaddr_in client_addr; + qb_loop_t * ml = (qb_loop_t*)data; + socklen_t sin_size = sizeof(struct sockaddr_in); + int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size); + + if (connected < 0) { + perror("accept"); + return QB_TRUE; + } + printf("I got a connection from (%s , %d)\n", + inet_ntoa(client_addr.sin_addr), + ntohs(client_addr.sin_port)); + + qb_loop_poll_add(ml, QB_LOOP_MED, + connected, POLLIN, + ml, sock_read_fn); + + return QB_TRUE; +} + +static int32_t +please_exit_fn(int32_t rsignal, void *data) +{ + qb_loop_t * ml = (qb_loop_t*)data; + + printf("Shutting down at you request...\n"); + qb_loop_stop(ml); + return QB_FALSE; +} + +int +main(int argc, char *argv[]) +{ + int sock; + int true_opt = 1; + struct sockaddr_in server_addr; + qb_loop_t * ml = qb_loop_create(); + + if ((sock = socket(AF_INET, + SOCK_STREAM, + 0)) == -1) { + perror("Socket"); + exit(1); + } + + if (setsockopt(sock, + SOL_SOCKET, + SO_REUSEADDR, + &true_opt, + sizeof(int)) == -1) { + perror("Setsockopt"); + exit(1); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(5000); + server_addr.sin_addr.s_addr = INADDR_ANY; + bzero(&(server_addr.sin_zero),8); + + printf("TCPServer binding to port 5000\n"); + if (bind(sock, + (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) { + perror("Unable to bind"); + exit(1); + } + + printf("TCPServer Waiting for client on port 5000\n"); + + if (listen(sock, 5) == -1) { + perror("Listen"); + exit(1); + } + + qb_loop_poll_add(ml, QB_LOOP_MED, + sock, POLLIN, + ml, sock_accept_fn); + + qb_loop_signal_add(ml, QB_LOOP_HIGH, + SIGINT, + ml, please_exit_fn, + NULL); + qb_loop_run(ml); + + close(sock); + return 0; +}
Signed-off-by: Angus Salkeld asalkeld@redhat.com --- examples/.gitignore | 2 + examples/Makefile.am | 12 ++- examples/ipcclient.c | 83 +++++++++++++ examples/ipcserver.c | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 428 insertions(+), 1 deletions(-) create mode 100644 examples/ipcclient.c create mode 100644 examples/ipcserver.c
diff --git a/examples/.gitignore b/examples/.gitignore index 861a32c..bf73ae4 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,3 +1,5 @@ simplelog tcpclient tcpserver +ipcclient +ipcserver diff --git a/examples/Makefile.am b/examples/Makefile.am index 867f9d8..f7dee65 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -21,7 +21,7 @@ MAINTAINERCLEANFILES = Makefiles.in EXTRA_DIST = CLEANFILES =
-noinst_PROGRAMS = simplelog tcpclient tcpserver +noinst_PROGRAMS = simplelog tcpclient tcpserver ipcclient ipcserver
simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include @@ -35,3 +35,13 @@ tcpserver_SOURCES = tcpserver.c $(top_builddir)/include/qb/qbloop.h tcpserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include tcpserver_LDADD = -lrt $(top_builddir)/lib/libqb.la
+ipcclient_SOURCES = ipcclient.c $(top_builddir)/include/qb/qbloop.h \ + $(top_builddir)/include/qb/qbipcc.h +ipcclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +ipcclient_LDADD = -lrt $(top_builddir)/lib/libqb.la + +ipcserver_SOURCES = ipcserver.c $(top_builddir)/include/qb/qbloop.h \ + $(top_builddir)/include/qb/qbipcs.h +ipcserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(GLIB_CFLAGS) +ipcserver_LDADD = -lrt $(top_builddir)/lib/libqb.la $(GLIB_LIBS) diff --git a/examples/ipcclient.c b/examples/ipcclient.c new file mode 100644 index 0000000..c43998f --- /dev/null +++ b/examples/ipcclient.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" +#include <signal.h> + +#include <qb/qbdefs.h> +#include <qb/qbutil.h> +#include <qb/qbipcc.h> + +#define MAX_MSG_SIZE (8192) + +int +main(int argc, char *argv[]) +{ + qb_ipcc_connection_t *conn; + int32_t res; + char *buffer[MAX_MSG_SIZE]; + + conn = qb_ipcc_connect("ipcserver", MAX_MSG_SIZE); + if (conn == NULL) { + perror("qb_ipcc_connect"); + exit(1); + } + + while(1) { + struct qb_ipc_request_header *req_header = (struct qb_ipc_request_header *)buffer; + struct qb_ipc_response_header *res_header = (struct qb_ipc_response_header *)buffer; + char *data = (char*)buffer + sizeof(struct qb_ipc_request_header); + + printf("SEND (q or Q to quit) : "); + if (gets(data) == NULL) { + continue; + } + + if (strcmp(data , "q") != 0 && + strcmp(data , "Q") != 0) { + req_header->id = QB_IPC_MSG_USER_START + 3; + req_header->size = sizeof(struct qb_ipc_request_header) + strlen(data) + 1; + res = qb_ipcc_send(conn, req_header, req_header->size); + if (res < 0) { + perror("qb_ipcc_send"); + } + } else { + break; + } + + if (res > 0) { + res = qb_ipcc_recv(conn, + buffer, + MAX_MSG_SIZE, -1); + if (res < 0) { + perror("qb_ipcc_recv"); + } + res_header = (struct qb_ipc_response_header*)buffer; + data = (char*)buffer + sizeof(struct qb_ipc_response_header); + data[res - sizeof(struct qb_ipc_response_header)] = '\0'; + + printf("Response[%d]: %s \n", res_header->id, data); + } + } + + qb_ipcc_disconnect(conn); + return EXIT_SUCCESS; +} + diff --git a/examples/ipcserver.c b/examples/ipcserver.c new file mode 100644 index 0000000..f26143a --- /dev/null +++ b/examples/ipcserver.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2006-2009 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Steven Dake sdake@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" +#include <signal.h> + +#include <qb/qbdefs.h> +#include <qb/qbutil.h> +#include <qb/qblog.h> +#include <qb/qbloop.h> +#include <qb/qbipcs.h> + +#ifdef HAVE_GLIB +#include <glib.h> +static GMainLoop *glib_loop; +static qb_array_t *gio_map; +#endif /* HAVE_GLIB */ + +static int32_t use_glib = QB_FALSE; +static qb_loop_t *bms_loop; +static qb_ipcs_service_t* s1; + +static int32_t +s1_connection_accept_fn(qb_ipcs_connection_t *c, uid_t uid, gid_t gid) +{ +#if 0 + if (uid == 0 && gid == 0) { + qb_log(LOG_INFO, "Authenticated connection"); + return 1; + } + qb_log(LOG_NOTICE, "BAD user!"); + return 0; +#else + return 0; +#endif +} + +static void +s1_connection_created_fn(qb_ipcs_connection_t *c) +{ + struct qb_ipcs_stats srv_stats; + + qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE); + qb_log(LOG_INFO, "Connection created (active:%d, closed:%d)", + srv_stats.active_connections, + srv_stats.closed_connections); +} + +static void +s1_connection_destroyed_fn(qb_ipcs_connection_t *c) +{ + qb_log(LOG_INFO, "Connection about to be freed"); +} + +static int32_t +s1_connection_closed_fn(qb_ipcs_connection_t *c) +{ + struct qb_ipcs_connection_stats stats; + struct qb_ipcs_stats srv_stats; + + qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE); + qb_ipcs_connection_stats_get(c, &stats, QB_FALSE); + qb_log(LOG_INFO, "Connection to pid:%d destroyed (active:%d, closed:%d)", + stats.client_pid, + srv_stats.active_connections, + srv_stats.closed_connections); + + qb_log(LOG_DEBUG, " Requests %"PRIu64"", stats.requests); + qb_log(LOG_DEBUG, " Responses %"PRIu64"", stats.responses); + qb_log(LOG_DEBUG, " Events %"PRIu64"", stats.events); + qb_log(LOG_DEBUG, " Send retries %"PRIu64"", stats.send_retries); + qb_log(LOG_DEBUG, " Recv retries %"PRIu64"", stats.recv_retries); + qb_log(LOG_DEBUG, " FC state %d", stats.flow_control_state); + qb_log(LOG_DEBUG, " FC count %"PRIu64"", stats.flow_control_count); + return 0; +} + +static int32_t +s1_msg_process_fn(qb_ipcs_connection_t *c, + void *data, size_t size) +{ + struct qb_ipc_request_header *req_pt = (struct qb_ipc_request_header *)data; + struct qb_ipc_response_header response; + ssize_t res; + struct iovec iov[2]; + char resp[100]; + + qb_log(LOG_DEBUG, "msg received (id:%d, size:%d)", + req_pt->id, req_pt->size); + response.size = sizeof(struct qb_ipc_response_header); + response.id = 13; + response.error = 0; + + snprintf(resp, 100, "ACK %zd bytes", size); + iov[0].iov_len = sizeof(response); + iov[0].iov_base = &response; + iov[1].iov_len = strlen(resp); + iov[1].iov_base = resp; + + res = qb_ipcs_response_sendv(c, iov, 2); + if (res < 0) { + qb_perror(LOG_ERR, "qb_ipcs_response_send"); + } + return 0; +} + +static void +sigusr1_handler(int32_t num) +{ + qb_log(LOG_DEBUG, "(%d)", num); + qb_ipcs_destroy(s1); + exit(0); +} + +static void +show_usage(const char *name) +{ + printf("usage: \n"); + printf("%s <options>\n", name); + printf("\n"); + printf(" options:\n"); + printf("\n"); + printf(" -h show this help text\n"); + printf(" -m use shared memory\n"); + printf(" -p use posix message queues\n"); + printf(" -s use sysv message queues\n"); + printf(" -u use unix sockets\n"); + printf(" -g use glib mainloop\n"); + printf("\n"); +} + +#ifdef HAVE_GLIB +struct gio_to_qb_poll { + int32_t is_used; + GIOChannel *channel; + int32_t events; + void * data; + qb_ipcs_dispatch_fn_t fn; + enum qb_loop_priority p; +}; + +static gboolean +gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer data) +{ + struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data; + gint fd = g_io_channel_unix_get_fd(gio); + + return (adaptor->fn(fd, condition, adaptor->data) == 0); +} + +static int32_t +my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts, + void *data, qb_ipcs_dispatch_fn_t fn) +{ + struct gio_to_qb_poll *adaptor; + GIOChannel *channel; + int32_t res = 0; + + res = qb_array_grow(gio_map, fd + 1); + if (res < 0) { + return res; + } + res = qb_array_index(gio_map, fd, (void**)&adaptor); + if (res < 0) { + return res; + } + if (adaptor->is_used) { + return -EEXIST; + } + + channel = g_io_channel_unix_new(fd); + if (!channel) { + return -ENOMEM; + } + + adaptor->channel = channel; + adaptor->fn = fn; + adaptor->events = evts; + adaptor->data = data; + adaptor->p = p; + adaptor->is_used = QB_TRUE; + + g_io_add_watch(channel, evts, gio_read_socket, adaptor); + return 0; +} + +static int32_t +my_g_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts, + void *data, qb_ipcs_dispatch_fn_t fn) +{ + return 0; +} + +static int32_t +my_g_dispatch_del(int32_t fd) +{ + struct gio_to_qb_poll *adaptor; + if (qb_array_index(gio_map, fd, (void**)&adaptor) == 0) { + g_io_channel_unref(adaptor->channel); + adaptor->is_used = QB_FALSE; + } + return 0; +} +#endif /* HAVE_GLIB */ + +static int32_t +my_job_add(enum qb_loop_priority p, void *data, qb_loop_job_dispatch_fn fn) +{ + return qb_loop_job_add(bms_loop, p, data, fn); +} + +static int32_t +my_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts, + void *data, qb_ipcs_dispatch_fn_t fn) +{ + return qb_loop_poll_add(bms_loop, p, fd, evts, data, fn); +} + +static int32_t +my_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts, + void *data, qb_ipcs_dispatch_fn_t fn) +{ + return qb_loop_poll_mod(bms_loop, p, fd, evts, data, fn); +} + +static int32_t +my_dispatch_del(int32_t fd) +{ + return qb_loop_poll_del(bms_loop, fd); +} + +int32_t +main(int32_t argc, char *argv[]) +{ + const char *options = "mpsugh"; + int32_t opt; + enum qb_ipc_type ipc_type = QB_IPC_SHM; + struct qb_ipcs_service_handlers sh = { + .connection_accept = s1_connection_accept_fn, + .connection_created = s1_connection_created_fn, + .msg_process = s1_msg_process_fn, + .connection_destroyed = s1_connection_destroyed_fn, + .connection_closed = s1_connection_closed_fn, + }; + struct qb_ipcs_poll_handlers ph = { + .job_add = my_job_add, + .dispatch_add = my_dispatch_add, + .dispatch_mod = my_dispatch_mod, + .dispatch_del = my_dispatch_del, + }; +#ifdef HAVE_GLIB + struct qb_ipcs_poll_handlers glib_ph = { + .job_add = NULL, /* FIXME */ + .dispatch_add = my_g_dispatch_add, + .dispatch_mod = my_g_dispatch_mod, + .dispatch_del = my_g_dispatch_del, + }; +#endif /* HAVE_GLIB */ + + while ((opt = getopt(argc, argv, options)) != -1) { + switch (opt) { + case 'm': + ipc_type = QB_IPC_SHM; + break; + case 's': + ipc_type = QB_IPC_SYSV_MQ; + break; + case 'u': + ipc_type = QB_IPC_SOCKET; + break; + case 'p': + ipc_type = QB_IPC_POSIX_MQ; + break; + case 'g': + use_glib = QB_TRUE; + break; + case 'h': + default: + show_usage(argv[0]); + exit(0); + break; + } + } + signal(SIGINT, sigusr1_handler); + + qb_log_init("ipcserver", LOG_USER, LOG_WARNING); + qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, __FILE__, + LOG_DEBUG); + qb_log_format_set(QB_LOG_STDERR, "%f:%l [%p] %b"); + qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); + + s1 = qb_ipcs_create("ipcserver", 0, ipc_type, &sh); + if (s1 == 0) { + qb_perror(LOG_ERR, "qb_ipcs_create"); + exit(1); + } + if (!use_glib) { + bms_loop = qb_loop_create(); + qb_ipcs_poll_handlers_set(s1, &ph); + qb_ipcs_run(s1); + qb_loop_run(bms_loop); + } else { +#ifdef HAVE_GLIB + glib_loop = g_main_loop_new(NULL, FALSE); + gio_map = qb_array_create(64, sizeof(struct gio_to_qb_poll)); + qb_ipcs_poll_handlers_set(s1, &glib_ph); + qb_ipcs_run(s1); + g_main_loop_run(glib_loop); +#else + qb_log(LOG_ERR, "You don't seem to have glib-devel installed.\n"); +#endif + } + return EXIT_SUCCESS; +}
quarterback-devel@lists.fedorahosted.org