diff options
-rw-r--r-- | pttbbs/daemon/barebone/Makefile | 14 | ||||
-rw-r--r-- | pttbbs/daemon/barebone/server.c | 194 | ||||
-rw-r--r-- | pttbbs/daemon/barebone/server.h | 19 | ||||
l---------[-rw-r--r--] | pttbbs/daemon/boardd/server.c | 195 | ||||
l---------[-rw-r--r--] | pttbbs/daemon/boardd/server.h | 20 |
5 files changed, 229 insertions, 213 deletions
diff --git a/pttbbs/daemon/barebone/Makefile b/pttbbs/daemon/barebone/Makefile new file mode 100644 index 00000000..d478d1db --- /dev/null +++ b/pttbbs/daemon/barebone/Makefile @@ -0,0 +1,14 @@ +# $Id$ + +SRCROOT= ../.. +.include "$(SRCROOT)/pttbbs.mk" + +PROG= server +SRCS= server.c + +CFLAGS+= $(LIBEVENT_CFLAGS) +LDFLAGS+= $(LIBEVENT_LIBS_L) + +LDADD+= $(LIBEVENT_LIBS_l) + +.include <bsd.prog.mk> diff --git a/pttbbs/daemon/barebone/server.c b/pttbbs/daemon/barebone/server.c new file mode 100644 index 00000000..2f9bbac1 --- /dev/null +++ b/pttbbs/daemon/barebone/server.c @@ -0,0 +1,194 @@ +// $Id$ +// Barebone TCP socket server daemon based on libevent 2.0 + +// Copyright (c) 2011, Chen-Yu Tsai <wens@csie.org> +// All rights reserved. + +// This is a simple TCP/IP server daemon based on libevent 2.0. +// This program does not depend on anything other than libevent 2.0. +// Without additional code linked in, this program alone will behave as an +// echo server. +// +// You can supply your client_read_cb(), client_event_cb(), setup_client(), or +// setup_program() functions to modify the behavior of the server. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include <event2/event.h> +#include <event2/buffer.h> +#include <event2/bufferevent.h> +#include <event2/util.h> +#include <event2/listener.h> + +#include "server.h" + +static const struct timeval timeout = {600, 0}; + +int +split_args(char *line, char ***argp) +{ + int argc = 0; + char *p, **argv; + + if ((argv = calloc(MAX_ARGS + 1, sizeof(char *))) == NULL) + return -1; + + while ((p = strsep(&line, " \t\r\n")) != NULL) { + argv[argc++] = p; + + if (argc == MAX_ARGS) + break; + } + + argv = realloc(argv, (argc + 1) * sizeof(char *)); + *argp = argv; + + return argc; +} + +void __attribute__((weak)) +client_read_cb(struct bufferevent *bev, void *ctx) +{ + bufferevent_write_buffer(bev, bufferevent_get_input(bev)); +} + +void __attribute__((weak)) +client_event_cb(struct bufferevent *bev, short events, void *ctx) +{ + if (events & BEV_EVENT_ERROR) + perror("Error from bufferevent"); + if (events & (BEV_EVENT_EOF | BEV_EVENT_TIMEOUT | BEV_EVENT_ERROR)) { + bufferevent_free(bev); + } +} + +void __attribute__((weak)) +setup_client(struct event_base *base, evutil_socket_t fd, + struct sockaddr *address, int socklen) +{ + struct bufferevent *bev = bufferevent_socket_new(base, fd, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + bufferevent_setcb(bev, client_read_cb, NULL, client_event_cb, NULL); + bufferevent_set_timeouts(bev, &timeout, &timeout); + bufferevent_enable(bev, EV_READ|EV_WRITE); +} + +static void +accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *address, int socklen, void *ctx) +{ + struct event_base *base = evconnlistener_get_base(listener); + return setup_client(base, fd, address, socklen); +} + +int __attribute__((weak)) daemon(int nochdir, int noclose); +void __attribute__((weak)) setup_program(); + +int main(int argc, char *argv[]) +{ + int ch, inetd = 0, run_as_daemon = 1; + const char *iface_ip = "127.0.0.1:5150"; + struct event_base *base; + struct evconnlistener *listener; + + while ((ch = getopt(argc, argv, "Dil:h")) != -1) + switch (ch) { + case 'D': + run_as_daemon = 0; + break; + case 'i': + inetd = 1; + break; + case 'l': + iface_ip = optarg; + break; + case 'h': + default: + fprintf(stderr, "usage: " " [-D] [-i] [-l interface_ip:port]\n"); + exit(EXIT_FAILURE); + } + + if (run_as_daemon && !inetd) + if (daemon(1, 1) < 0) { + perror("daemon"); + exit(EXIT_FAILURE); + } + + base = event_base_new(); + assert(base); + + if (!inetd) { + struct sockaddr sa; + int len = sizeof(sa); + + if (evutil_parse_sockaddr_port(iface_ip, &sa, &len) < 0) + exit(EXIT_FAILURE); + + listener = evconnlistener_new_bind(base, accept_conn_cb, NULL, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE, + 100, &sa, len); + + if (!listener) + exit(EXIT_FAILURE); + } else { + struct sockaddr sa; + socklen_t len = sizeof(sa); + getpeername(0, &sa, &len); + setup_client(base, 0, &sa, len); + } + + if (setup_program) + setup_program(); + + signal(SIGPIPE, SIG_IGN); + + event_base_dispatch(base); + + return 0; +} + +#ifdef __linux__ + +int +daemon(int nochdir, int noclose) +{ + int fd; + + switch (fork()) { + case -1: + return -1; + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return -1; + + if (!nochdir) + chdir("/"); + + if (!noclose && (fd = open("/dev/null", O_RDWR)) >= 0) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + if (fd > 2) + close(fd); + } + + return 0; +} + +#endif // __linux__ diff --git a/pttbbs/daemon/barebone/server.h b/pttbbs/daemon/barebone/server.h new file mode 100644 index 00000000..9cba93b7 --- /dev/null +++ b/pttbbs/daemon/barebone/server.h @@ -0,0 +1,19 @@ +// $Id$ + +// Copyright (c) 2011, Chen-Yu Tsai <wens@csie.org> +// All rights reserved. + +#include <event2/listener.h> +#include <event2/bufferevent.h> + +#ifndef MAX_ARGS +#define MAX_ARGS 100 +#endif + +extern void client_read_cb(struct bufferevent *bev, void *ctx); +extern void client_event_cb(struct bufferevent *bev, short events, void *ctx); +extern void setup_client(struct event_base *base, evutil_socket_t fd, + struct sockaddr *address, int socklen); +extern void setup_program(); + +extern int split_args(char *line, char ***argp); diff --git a/pttbbs/daemon/boardd/server.c b/pttbbs/daemon/boardd/server.c index 2f9bbac1..88ec683f 100644..120000 --- a/pttbbs/daemon/boardd/server.c +++ b/pttbbs/daemon/boardd/server.c @@ -1,194 +1 @@ -// $Id$ -// Barebone TCP socket server daemon based on libevent 2.0 - -// Copyright (c) 2011, Chen-Yu Tsai <wens@csie.org> -// All rights reserved. - -// This is a simple TCP/IP server daemon based on libevent 2.0. -// This program does not depend on anything other than libevent 2.0. -// Without additional code linked in, this program alone will behave as an -// echo server. -// -// You can supply your client_read_cb(), client_event_cb(), setup_client(), or -// setup_program() functions to modify the behavior of the server. - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/socket.h> -#include <netinet/in.h> - -#include <event2/event.h> -#include <event2/buffer.h> -#include <event2/bufferevent.h> -#include <event2/util.h> -#include <event2/listener.h> - -#include "server.h" - -static const struct timeval timeout = {600, 0}; - -int -split_args(char *line, char ***argp) -{ - int argc = 0; - char *p, **argv; - - if ((argv = calloc(MAX_ARGS + 1, sizeof(char *))) == NULL) - return -1; - - while ((p = strsep(&line, " \t\r\n")) != NULL) { - argv[argc++] = p; - - if (argc == MAX_ARGS) - break; - } - - argv = realloc(argv, (argc + 1) * sizeof(char *)); - *argp = argv; - - return argc; -} - -void __attribute__((weak)) -client_read_cb(struct bufferevent *bev, void *ctx) -{ - bufferevent_write_buffer(bev, bufferevent_get_input(bev)); -} - -void __attribute__((weak)) -client_event_cb(struct bufferevent *bev, short events, void *ctx) -{ - if (events & BEV_EVENT_ERROR) - perror("Error from bufferevent"); - if (events & (BEV_EVENT_EOF | BEV_EVENT_TIMEOUT | BEV_EVENT_ERROR)) { - bufferevent_free(bev); - } -} - -void __attribute__((weak)) -setup_client(struct event_base *base, evutil_socket_t fd, - struct sockaddr *address, int socklen) -{ - struct bufferevent *bev = bufferevent_socket_new(base, fd, - BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); - bufferevent_setcb(bev, client_read_cb, NULL, client_event_cb, NULL); - bufferevent_set_timeouts(bev, &timeout, &timeout); - bufferevent_enable(bev, EV_READ|EV_WRITE); -} - -static void -accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, - struct sockaddr *address, int socklen, void *ctx) -{ - struct event_base *base = evconnlistener_get_base(listener); - return setup_client(base, fd, address, socklen); -} - -int __attribute__((weak)) daemon(int nochdir, int noclose); -void __attribute__((weak)) setup_program(); - -int main(int argc, char *argv[]) -{ - int ch, inetd = 0, run_as_daemon = 1; - const char *iface_ip = "127.0.0.1:5150"; - struct event_base *base; - struct evconnlistener *listener; - - while ((ch = getopt(argc, argv, "Dil:h")) != -1) - switch (ch) { - case 'D': - run_as_daemon = 0; - break; - case 'i': - inetd = 1; - break; - case 'l': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: " " [-D] [-i] [-l interface_ip:port]\n"); - exit(EXIT_FAILURE); - } - - if (run_as_daemon && !inetd) - if (daemon(1, 1) < 0) { - perror("daemon"); - exit(EXIT_FAILURE); - } - - base = event_base_new(); - assert(base); - - if (!inetd) { - struct sockaddr sa; - int len = sizeof(sa); - - if (evutil_parse_sockaddr_port(iface_ip, &sa, &len) < 0) - exit(EXIT_FAILURE); - - listener = evconnlistener_new_bind(base, accept_conn_cb, NULL, - LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE, - 100, &sa, len); - - if (!listener) - exit(EXIT_FAILURE); - } else { - struct sockaddr sa; - socklen_t len = sizeof(sa); - getpeername(0, &sa, &len); - setup_client(base, 0, &sa, len); - } - - if (setup_program) - setup_program(); - - signal(SIGPIPE, SIG_IGN); - - event_base_dispatch(base); - - return 0; -} - -#ifdef __linux__ - -int -daemon(int nochdir, int noclose) -{ - int fd; - - switch (fork()) { - case -1: - return -1; - case 0: - break; - default: - _exit(0); - } - - if (setsid() == -1) - return -1; - - if (!nochdir) - chdir("/"); - - if (!noclose && (fd = open("/dev/null", O_RDWR)) >= 0) { - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - - if (fd > 2) - close(fd); - } - - return 0; -} - -#endif // __linux__ +../barebone/server.c
\ No newline at end of file diff --git a/pttbbs/daemon/boardd/server.h b/pttbbs/daemon/boardd/server.h index 9cba93b7..75e7076e 100644..120000 --- a/pttbbs/daemon/boardd/server.h +++ b/pttbbs/daemon/boardd/server.h @@ -1,19 +1 @@ -// $Id$ - -// Copyright (c) 2011, Chen-Yu Tsai <wens@csie.org> -// All rights reserved. - -#include <event2/listener.h> -#include <event2/bufferevent.h> - -#ifndef MAX_ARGS -#define MAX_ARGS 100 -#endif - -extern void client_read_cb(struct bufferevent *bev, void *ctx); -extern void client_event_cb(struct bufferevent *bev, short events, void *ctx); -extern void setup_client(struct event_base *base, evutil_socket_t fd, - struct sockaddr *address, int socklen); -extern void setup_program(); - -extern int split_args(char *line, char ***argp); +../barebone/server.h
\ No newline at end of file |