From 2d6203a7827db44bbb4fd8759c4e217f7adc5264 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ji=C5=99=C3=AD=20=C5=A0kr=C3=A1bal?= Date: Mon, 11 Oct 2004 12:30:19 +0000 Subject: [PATCH] - added a little examle - API changed - parameters setting functionality added --- org.glite.lb.server-bones/Makefile | 12 +- org.glite.lb.server-bones/examples/cnt_example.c | 175 ++++++++++++++++++++ org.glite.lb.server-bones/examples/srv_example.c | 199 +++++++++++++++++++++++ org.glite.lb.server-bones/interface/srvbones.h | 14 +- org.glite.lb.server-bones/src/srvbones.c | 129 +++++++++------ 5 files changed, 475 insertions(+), 54 deletions(-) create mode 100644 org.glite.lb.server-bones/examples/cnt_example.c create mode 100644 org.glite.lb.server-bones/examples/srv_example.c diff --git a/org.glite.lb.server-bones/Makefile b/org.glite.lb.server-bones/Makefile index 952d903..ea67dd9 100644 --- a/org.glite.lb.server-bones/Makefile +++ b/org.glite.lb.server-bones/Makefile @@ -19,10 +19,10 @@ ares_prefix=/opt/ares -include Makefile.inc -VPATH=${top_srcdir}/src:${top_srcdir}/test +VPATH=${top_srcdir}/src:${top_srcdir}/examples DEBUG:=-g -O0 -Wall -CFLAGS:= ${DEBUG} -I${top_srcdir}/interface -I${top_srcdir}/src -I. +CFLAGS:= ${DEBUG} -I${top_srcdir}/interface COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/lib ${LDFLAGS} @@ -38,7 +38,7 @@ HDRS:=srvbones.h default all: compile -compile: ${STATICLIB} ${LTLIB} +compile: ${STATICLIB} ${LTLIB} example ${STATICLIB}: ${OBJS} ar crv $@ ${OBJS} @@ -53,13 +53,13 @@ stage: compile check: example_test -echo "No unit tests so far." -example_test: srv_example client_example +example: srv_example cnt_example srv_example: srv_example.o ${LINK} -o $@ ${LTLIB} srv_example.o -client_example: client.o - ${LINK} -o $@ client.o +cnt_example: cnt_example.o + ${LINK} -o $@ cnt_example.o doc: diff --git a/org.glite.lb.server-bones/examples/cnt_example.c b/org.glite.lb.server-bones/examples/cnt_example.c new file mode 100644 index 0000000..5f73a23 --- /dev/null +++ b/org.glite.lb.server-bones/examples/cnt_example.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef dprintf +#define dprintf(x) { if (debug) printf x; fflush(stdout); } +#endif + +#define DEF_MSG "Test message\n" +#define DEF_PORT 9999 + +static struct option opts[] = { + { "help", no_argument, NULL, 'h'}, + { "debug", no_argument, NULL, 'd'}, + { "msg", required_argument, NULL, 'm'}, + { "port", required_argument, NULL, 'p'}, +}; + +int debug = 0; +int port = DEF_PORT; +char *msg = NULL; + +static int writen(int fd, char *ptr, int nbytes); +static int readln(int fd, char *out); + +static void usage(char *me) +{ + fprintf(stderr, + "usage: %s [option]\n" + " -h, --help print this screen\n" + " -d, --debug prints debug messages\n" + " -m, --msg message to send\n" + " -p, --port service port\n", me); +} + + +int main(int argc, char **argv) +{ + struct sockaddr_in addr; + char buff[512], + *me; + int opt, + sock, + n; + + + me = strrchr(argv[0], '/'); + if ( me ) me++; else me = argv[0]; + while ( (opt = getopt_long(argc, argv,"p:m:hd", opts, NULL)) != EOF ) + { + switch ( opt ) + { + case 'm': + msg = strdup(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'd': debug = 1; break; + case 'h': usage(me); return 0; + case '?': usage(me); return 1; + } + } + + bzero((char *) &addr, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(port); + if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) + { + perror("socket"); + exit(1); + } + if ( connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) + { + perror("connect"); + exit(1); + } + n = strlen(msg? msg: DEF_MSG); + if ( writen(sock, msg? msg: DEF_MSG, n) != n ) + { + dprintf(("error writing message\n")); + exit(1); + } + printf("reply: "); fflush(stdout); + n = readln(sock, buff); + if ( n < 0 ) + { + perror("read() reply error"); + return 1; + } + writen(0, buff, n); + close(sock); + + return 0; +} + +int writen(int fd, char *ptr, int nbytes) +{ + int nleft, nwritten; + + nleft = nbytes; + dprintf(("start writing %d bytes\n", nbytes)); + while ( nleft > 0 ) + { + nwritten = write(fd, ptr, nleft); + dprintf(("written %d bytes", nwritten)); + if ( nwritten <= 0 ) + return (nwritten); + + nleft -= nwritten; + ptr += nwritten; + dprintf((" (left %d bytes)\n", nleft)); + } + + dprintf(("written %d bytes (return: %d)\n", nwritten, nbytes - nleft)); + return (nbytes - nleft); +} + +#define BUFFER_SZ 512 + +int readln(int fd, char *out) +{ + static char buffer[BUFFER_SZ]; + static char *buffer_end = buffer; + int n; + + + dprintf(("reading line\n")); + while ( 1 ) { + if ( buffer_end - buffer ) { + /* buffer contains data + */ + char *endl; + + dprintf(("nonempty buffer\n")); + if ( (endl = memchr(buffer, '\n', buffer_end-buffer)) ) { + int linesz = endl-buffer+1; + + dprintf(("using buffer data\n")); + memcpy(out, buffer, linesz); + if ( endl+1 != buffer_end ) + memmove(buffer, endl+1, buffer_end-endl-1); + buffer_end -= linesz; + return linesz; + } + } + dprintf(("reading...\n")); + n = read(fd, buffer_end, BUFFER_SZ-(buffer_end-buffer)); + if ( n < 0 ) { + if ( errno == EAGAIN ) continue; + dprintf(("reading error\n")); + return n; + } + else if ( n == 0 ) { + int ret = buffer_end-buffer; + dprintf(("end of reading - returning %d bytes\n", ret)); + memcpy(out, buffer, ret); + buffer_end = buffer; + return ret; + } + + dprintf(("read %d bytes\n", n)); + buffer_end += n; + } + + return 0; +} diff --git a/org.glite.lb.server-bones/examples/srv_example.c b/org.glite.lb.server-bones/examples/srv_example.c new file mode 100644 index 0000000..10f7702 --- /dev/null +++ b/org.glite.lb.server-bones/examples/srv_example.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srvbones.h" + +#ifndef dprintf +#define dprintf(x) { if (debug) printf x; fflush(stdout); } +#endif + +#define sizofa(a) (sizeof(a)/sizeof((a)[0])) + +int debug = 1; + +static int writen(int fd, char *ptr, int nbytes); +static int readln(int fd, char *out, int nbytes); +static int echo(int, struct timeval, void *); +static int upper_echo(int, struct timeval, void *); + +#define ECHO_PORT 9999 +#define UPPER_ECHO_PORT 9998 + +#define SRV_ECHO 0 +#define SRV_UPPER_ECHO 1 + +static struct glite_srvbones_service service_table[] = { + { "Echo Service", -1, NULL, echo, NULL, NULL }, + { "Upper Echo Service", -1, NULL, upper_echo, NULL, NULL } +}; + +int main(void) +{ + struct sockaddr_in myaddr; + + + if ( ((service_table[SRV_ECHO].conn = socket(AF_INET, SOCK_STREAM, 0)) == -1) + || ((service_table[SRV_UPPER_ECHO].conn = socket(AF_INET, SOCK_STREAM, 0)) == -1) ) + { + perror("socket"); + exit(1); + } + + bzero((char *) &myaddr, sizeof(myaddr)); + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = htonl(INADDR_ANY); + myaddr.sin_port = htons(ECHO_PORT); + if ( bind(service_table[SRV_ECHO].conn, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1 ) + { + perror("bind"); + exit(1); + } + bzero((char *) &myaddr, sizeof(myaddr)); + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = htonl(INADDR_ANY); + myaddr.sin_port = htons(UPPER_ECHO_PORT); + if ( bind(service_table[SRV_UPPER_ECHO].conn, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1 ) + { + perror("bind"); + exit(1); + } + + if ( listen(service_table[SRV_ECHO].conn, 10) + || listen(service_table[SRV_UPPER_ECHO].conn, 10) ) + { + perror("listen()"); + exit(1); + } + + glite_srvbones_run(NULL, service_table, sizofa(service_table), 1); + + + return 0; +} + +int upper_echo(int fd, struct timeval client_start, void *data) +{ + int n, i; + char line[80]; + + n = readln(fd, line, 80); + if ( n < 0 ) + { + perror("read() message"); + return n; + } + else if ( n == 0 ) + return 0; + + for ( i = 0; i < n; i++ ) + line[i] = toupper(line[i]); + + if ( writen(fd, line, n) != n ) + { + perror("write() message back"); + return -1; + } + + return 0; +} + +int echo(int fd, struct timeval client_start, void *data) +{ + int n; + char line[80]; + + n = readln(fd, line, 80); + dprintf(("%d bytes read\n", n)); + if ( n < 0 ) + { + perror("read() message"); + return n; + } + else if ( n == 0 ) + return 0; + + if ( writen(fd, line, n) != n ) + { + perror("write() message back"); + return -1; + } + + return 0; +} + +int writen(int fd, char *ptr, int nbytes) +{ + int nleft, nwritten; + + nleft = nbytes; + dprintf(("start writing %d bytes\n", nbytes)); + while ( nleft > 0 ) { + nwritten = write(fd, ptr, nleft); + dprintf(("written %d bytes", nwritten)); + if ( nwritten <= 0 ) + return (nwritten); + + nleft -= nwritten; + ptr += nwritten; + dprintf((" (left %d bytes)\n", nleft)); + } + + dprintf(("written %d bytes (return: %d)\n", nwritten, nbytes - nleft)); + return (nbytes - nleft); +} + +#define BUFFER_SZ 512 + +int readln(int fd, char *out, int nbytes) +{ + static char buffer[BUFFER_SZ]; + static char *buffer_end = buffer; + int n; + + + dprintf(("reading line\n")); + while ( 1 ) { + if ( buffer_end - buffer ) { + /* buffer contains data + */ + char *endl; + + dprintf(("nonempty buffer\n")); + if ( (endl = memchr(buffer, '\n', buffer_end-buffer)) ) { + int linesz = endl-buffer+1; + + memcpy(out, buffer, linesz); + if ( endl+1 != buffer_end ) memmove(buffer, endl+1, buffer_end-endl-1); + buffer_end -= linesz; + return linesz; + } + } + + dprintf(("reding...\n")); + n = read(fd, buffer_end, BUFFER_SZ-(buffer_end-buffer)); + if ( n < 0 ) { + if ( errno == EAGAIN ) n = 0; + else return n; + } + if ( n == 0 ) { + int ret = buffer_end-buffer; + dprintf(("end of reading - returning %d bytes\n", ret)); + memcpy(out, buffer, ret); + buffer_end = buffer; + return ret; + } + dprintf(("read %d bytes\n", n)); + + buffer_end += n; + } + + return 0; +} diff --git a/org.glite.lb.server-bones/interface/srvbones.h b/org.glite.lb.server-bones/interface/srvbones.h index 3abcd05..1fb87ed 100644 --- a/org.glite.lb.server-bones/interface/srvbones.h +++ b/org.glite.lb.server-bones/interface/srvbones.h @@ -5,6 +5,18 @@ extern "C" { #endif +typedef enum _glite_srvbones_param_t { + GLITE_SBPARAM_SLAVES_CT, /* default number of slaves */ + GLITE_SBPARAM_SLAVE_OVERLOAD, /* queue items per slave */ + GLITE_SBPARAM_SLAVE_CONNS_MAX, /* commit suicide after that many */ + /* connections */ + GLITE_SBPARAM_CLNT_TIMEOUT, /* keep idle connection that many */ + /* seconds */ + GLITE_SBPARAM_TOTAL_CLNT_TIMEOUT, /* client may ask one slave multiple */ + /* times but only limited time to */ + /* avoid DoS attacks */ +} glite_srvbones_param_t; + typedef int (*slave_data_init_hnd)(void **); struct glite_srvbones_service { @@ -16,12 +28,12 @@ struct glite_srvbones_service { int (*on_disconnect_hnd)(int conn, void *clnt_data); }; +extern int glite_srvbones_set_param(glite_srvbones_param_t param, ...); /* * slaves_ct - forked slaves count * slave_data_init_hnd - callback initializing client data on every slave */ extern int glite_srvbones_run( - int slaves_ct, slave_data_init_hnd slave_data_init, struct glite_srvbones_service *service_table, size_t table_sz, diff --git a/org.glite.lb.server-bones/src/srvbones.c b/org.glite.lb.server-bones/src/srvbones.c index 88e8c76..9c5d865 100644 --- a/org.glite.lb.server-bones/src/srvbones.c +++ b/org.glite.lb.server-bones/src/srvbones.c @@ -2,54 +2,48 @@ #include #include #include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include #include -#include #include #include #include #include -#include -#include -#include -#include -#include +#include #include "srvbones.h" +#define SLAVES_CT 5 /* default number of slaves */ #define SLAVE_OVERLOAD 10 /* queue items per slave */ +#define SLAVE_CONNS_MAX 500 /* commit suicide after that many connections */ +#define SLAVE_CHECK_SIGNALS 2 /* how often to check signals while waiting for recv_mesg */ #define CLNT_TIMEOUT 10 /* keep idle connection that many seconds */ #define TOTAL_CLNT_TIMEOUT 60 /* one client may ask one slave multiple times */ /* but only limited time to avoid DoS attacks */ -#define CLNT_REJECT_TIMEOUT 100000 /* time limit for client rejection in !usec! */ -#define SLAVE_CONNS_MAX 500 /* commit suicide after that many connections */ -#define SLAVE_CHECK_SIGNALS 2 /* how often to check signals while waiting for recv_mesg */ -#define WATCH_TIMEOUT 1800 /* wake up to check updated credentials */ #ifndef dprintf #define dprintf(x) { if (debug) printf x; } #endif -static int debug = 0; +static int running = 0; +static int debug = 0; static volatile int die = 0, child_died = 0; static unsigned long clnt_dispatched = 0, clnt_accepted = 0; -static int slaves; + static struct glite_srvbones_service *services; static int services_ct; +static int set_slaves_ct = SLAVES_CT; +static int set_slave_overload = SLAVE_OVERLOAD; +static int set_slave_conns_max = SLAVE_CONNS_MAX; +static struct timeval set_clnt_to = {CLNT_TIMEOUT, 0}; +static struct timeval set_total_clnt_to = {TOTAL_CLNT_TIMEOUT, 0}; + + static int dispatchit(int, int, int); static int do_sendmsg(int, int, unsigned long, int); static int do_recvmsg(int, int *, unsigned long *, int *); @@ -58,10 +52,41 @@ static void catchsig(int); static void catch_chld(int sig); static int slave(int (*)(void **), int); +static void glite_srvbones_set_slaves_ct(int); +static void glite_srvbones_set_slave_overload(int); +static void glite_srvbones_set_slave_conns_max(int); +static void glite_srvbones_set_clnt_to(struct timeval *); +static void glite_srvbones_set_total_clnt_to(struct timeval *); + + +int glite_srvbones_set_param(glite_srvbones_param_t param, ...) +{ + va_list ap; + if ( running ) { + dprintf(("Attempting to set srv-bones parameter on running server")); + return -1; + } + + va_start(ap, param); + switch ( param ) { + case GLITE_SBPARAM_SLAVES_CT: + glite_srvbones_set_slaves_ct(va_arg(ap,int)); break; + case GLITE_SBPARAM_SLAVE_OVERLOAD: + glite_srvbones_set_slave_overload(va_arg(ap,int)); break; + case GLITE_SBPARAM_SLAVE_CONNS_MAX: + glite_srvbones_set_slave_conns_max(va_arg(ap,int)); break; + case GLITE_SBPARAM_CLNT_TIMEOUT: + glite_srvbones_set_clnt_to(va_arg(ap,struct timeval *)); break; + case GLITE_SBPARAM_TOTAL_CLNT_TIMEOUT: + glite_srvbones_set_total_clnt_to(va_arg(ap,struct timeval *)); break; + } + va_end(ap); + + return 0; +} int glite_srvbones_run( - int slaves_ct, slave_data_init_hnd slave_data_init, struct glite_srvbones_service *service_table, size_t table_sz, @@ -73,10 +98,9 @@ int glite_srvbones_run( assert(service_table); - assert(slaves_ct > 0); + assert(table_sz > 0); services = service_table; - slaves = slaves_ct; services_ct = table_sz; debug = dbg; @@ -107,14 +131,13 @@ int glite_srvbones_run( sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, NULL); - for ( i = 0; i < slaves; i++ ) + for ( i = 0; i < set_slaves_ct; i++ ) slave(slave_data_init, sock_slave[1]); while ( !die ) { fd_set fds; int ret, mx; - struct timeval watch_to = { WATCH_TIMEOUT, 0 }; FD_ZERO(&fds); @@ -126,15 +149,13 @@ int glite_srvbones_run( } sigprocmask(SIG_UNBLOCK, &sset, NULL); - ret = select(mx+1, &fds, NULL, NULL, &watch_to); + ret = select(mx+1, &fds, NULL, NULL, NULL); sigprocmask(SIG_BLOCK, &sset, NULL); if ( ret == -1 && errno != EINTR ) { - if ( debug ) - perror("select()"); - else - syslog(LOG_CRIT,"select(): %m"); + if ( debug ) perror("select()"); + else syslog(LOG_CRIT,"select(): %m"); return 1; } @@ -180,8 +201,7 @@ int glite_srvbones_run( } dprintf(("[master] Terminating on signal %d\n", die)); - if (!debug) - syslog(LOG_INFO, "Terminating on signal %d\n", die); + if (!debug) syslog(LOG_INFO, "Terminating on signal %d\n", die); kill(0, die); return 0; @@ -220,7 +240,7 @@ static int dispatchit(int sock_slave, int sock, int sidx) ret = 0; if ( ( clnt_dispatched < clnt_accepted /* wraparound */ - || clnt_dispatched - clnt_accepted < slaves * SLAVE_OVERLOAD) + || clnt_dispatched - clnt_accepted < set_slaves_ct * set_slave_overload) && !(ret = do_sendmsg(sock_slave, conn, clnt_dispatched++, sidx)) ) { /* all done @@ -293,7 +313,7 @@ static int slave(slave_data_init_hnd data_init_hnd, int sock) */ exit(1); - while ( !die && (conn_cnt < SLAVE_CONNS_MAX || conn >= 0) ) + while ( !die && (conn_cnt < set_slave_conns_max || conn >= 0) ) { fd_set fds; int max = sock, @@ -303,8 +323,8 @@ static int slave(slave_data_init_hnd data_init_hnd, int sock) kick_client = 0; unsigned long seq; struct timeval check_to = { SLAVE_CHECK_SIGNALS, 0}, - total_to = { TOTAL_CLNT_TIMEOUT, 0}, - client_to = { CLNT_TIMEOUT,0 }, + total_to = set_total_clnt_to, + client_to = set_clnt_to, now; @@ -372,7 +392,7 @@ static int slave(slave_data_init_hnd data_init_hnd, int sock) continue; } - if ( FD_ISSET(sock, &fds) && conn_cnt < SLAVE_CONNS_MAX ) + if ( FD_ISSET(sock, &fds) && conn_cnt < set_slave_conns_max ) { if ( conn >= 0 ) usleep(100000 + 1000 * (random() % 200)); if ( do_recvmsg(sock, &newconn, &seq, &newsrv) ) switch ( errno ) @@ -389,16 +409,6 @@ static int slave(slave_data_init_hnd data_init_hnd, int sock) if ( kick_client && conn >= 0 ) { - /* - * XXX: neco jako on_disconnect_hnd - * - if ( ctx->connPool[ctx->connToUse].gss.context != GSS_C_NO_CONTEXT) - { - struct timeval to = { 0, CLNT_REJECT_TIMEOUT }; - edg_wll_gss_close(&ctx->connPool[ctx->connToUse].gss,&to); - } - edg_wll_FreeContext(ctx); - */ if ( services[srv].on_disconnect_hnd ) services[srv].on_disconnect_hnd(conn, clnt_data); close(conn); @@ -563,3 +573,28 @@ static int do_recvmsg(int from_sock, int *sock, unsigned long *clnt_accepted,int return 0; } + +static void glite_srvbones_set_slaves_ct(int n) +{ + set_slaves_ct = (n == -1)? SLAVES_CT: n; +} + +static void glite_srvbones_set_slave_overload(int n) +{ + set_slave_overload = (n == -1)? SLAVE_OVERLOAD: n; +} + +static void glite_srvbones_set_slave_conns_max(int n) +{ + set_slave_conns_max = (n == -1)? SLAVE_CONNS_MAX: n; +} + +static void glite_srvbones_set_clnt_to(struct timeval *t) +{ + set_clnt_to = t? (struct timeval){CLNT_TIMEOUT, 0}: *t; +} + +static void glite_srvbones_set_total_clnt_to(struct timeval *t) +{ + set_total_clnt_to = t? (struct timeval){TOTAL_CLNT_TIMEOUT, 0}: *t; +} -- 1.8.2.3