uni

University stuff
git clone git://git.margiolis.net/uni.git
Log | Files | Refs | README | LICENSE

commit d02f9b5e2b44d8502d8d01f316317a548a3ea9d8
parent 37a769ca5b7668e3b593fddf42cdeeaca1512049
Author: Christos Margiolis <christos@margiolis.net>
Date:   Tue,  3 May 2022 00:40:14 +0300

almost done with ex1

Diffstat:
Ac_distributed_sys/ex1/Makefile | 9+++++++++
Ac_distributed_sys/ex1/Makefile.rpc | 42++++++++++++++++++++++++++++++++++++++++++
Ac_distributed_sys/ex1/notes | 15+++++++++++++++
Ac_distributed_sys/ex1/rpc.x | 35+++++++++++++++++++++++++++++++++++
Ac_distributed_sys/ex1/rpc_client.c | 314+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ac_distributed_sys/ex1/rpc_server.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ac_distributed_sys/ex1/sock_client.c | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 691 insertions(+), 0 deletions(-)

diff --git a/c_distributed_sys/ex1/Makefile b/c_distributed_sys/ex1/Makefile @@ -0,0 +1,9 @@ +CC = cc + +all: + make -f Makefile.rpc + ${CC} sock_client.c -o sock_client + +clean: + make -f Makefile.rpc clean + rm -f sock_client *.core diff --git a/c_distributed_sys/ex1/Makefile.rpc b/c_distributed_sys/ex1/Makefile.rpc @@ -0,0 +1,42 @@ +# This is a template makefile generated by rpcgen + +# Parameters + +CLIENT = rpc_client +SERVER = rpc_server + +SOURCES_CLNT.c = +SOURCES_CLNT.h = +SOURCES_SVC.c = +SOURCES_SVC.h = +SOURCES.x = rpc.x + +TARGETS_SVC.c = rpc_server.c rpc_svc.c rpc_xdr.c +TARGETS_CLNT.c = rpc_client.c rpc_clnt.c rpc_xdr.c +TARGETS = rpc.h rpc_xdr.c rpc_clnt.c rpc_svc.c + +OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o) +OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o) +# Compiler flags +CFLAGS += -g -DRPC_SVC_FG +RPCGENFLAGS = -C + +# Targets + +all : $(CLIENT) $(SERVER) + +$(TARGETS) : $(SOURCES.x) + rpcgen $(RPCGENFLAGS) $(SOURCES.x) + +$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) + +$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) + +$(CLIENT) : $(OBJECTS_CLNT) + $(CC) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) $(CFLAGS) + +$(SERVER) : $(OBJECTS_SVC) + $(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS) $(CFLAGS) + +clean: + rm -f core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER) diff --git a/c_distributed_sys/ex1/notes b/c_distributed_sys/ex1/notes @@ -0,0 +1,15 @@ +# write rpc.x +rpcgen -Ss -C > rpc_server.c +rpcgen -Sc -C > rpc.client.c +rpcgen -Sm > Makefile.rpc +# fill rpc_server, rpc_client stubs +# edit Makefile.rpc... + CFLAGS + RPCFLAGS + TARGETS_* +# write sock_client +# write Makefile +service rpcbind onestart +./rpc_server +./rpc_client +./sock_client diff --git a/c_distributed_sys/ex1/rpc.x b/c_distributed_sys/ex1/rpc.x @@ -0,0 +1,35 @@ +struct arg_arr { + int n; + int arr<>; +}; + +struct arg_prod { + float a; + struct arg_arr arr; +}; + +struct minmax { + int arr<2>; +}; + +struct float_arr { + float arr<>; +}; + +program calc_avg_PROG { + version calc_avg_VERS { + float calc_avg(arg_arr) = 1; + } = 1; +} = 0x20000000; + +program calc_minmax_PROG { + version calc_minmax_VERS { + struct minmax calc_minmax(arg_arr) = 1; + } = 1; +} = 0x20000001; + +program calc_prod_PROG { + version calc_prod_VERS { + struct float_arr calc_prod(arg_prod) = 1; + } = 1; +} = 0x20000002; diff --git a/c_distributed_sys/ex1/rpc_client.c b/c_distributed_sys/ex1/rpc_client.c @@ -0,0 +1,314 @@ +#include <sys/socket.h> +#include <sys/types.h> + +#include <arpa/inet.h> +#include <netdb.h> +#include <netinet/in.h> + +#include <err.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "rpc.h" + +static void serve_client(char *, int); +static void sighandler(int); +static void *emalloc(size_t); +static void usage(void); + +static char *argv0; +/* becomes true when a termination signal is caught */ +static volatile sig_atomic_t f_quit = 0; + +void +calc_avg_prog_1(char *host, int sock) +{ + CLIENT *clnt; + float *result_1; + arg_arr calc_avg_1_arg; + int *np, *arrp; + +#ifndef DEBUG + clnt = clnt_create(host, calc_avg_PROG, calc_avg_VERS, "netpath"); + if (clnt == (CLIENT *) NULL) { + clnt_pcreateerror(host); + exit(1); + } +#endif /* DEBUG */ + + /* avoid typing all this */ + np = &calc_avg_1_arg.n; + + /* receive number of elements */ + if (recv(sock, np, sizeof(int), 0) < 0) + goto fail; + calc_avg_1_arg.arr.arr_len = *np; + calc_avg_1_arg.arr.arr_val = emalloc(*np * sizeof(int)); + arrp = calc_avg_1_arg.arr.arr_val; + + /* receive array */ + if (recv(sock, arrp, *np * sizeof(int), 0) < 0) + goto fail; + + /* make RPC */ + result_1 = calc_avg_1(&calc_avg_1_arg, clnt); + if (result_1 == (float *) NULL) { + clnt_perror(clnt, "call failed"); + } + + /* send results back to sock_client */ + printf("[%s] sock: %d\tserver response: avg: %.3f\n", argv0, sock, *result_1); + if (send(sock, result_1, sizeof(float), 0) < 0) + goto fail; + return; +fail: + /* we failed... */ + fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); + close(sock); + if (arrp != NULL) + free(arrp); +#ifndef DEBUG + clnt_destroy(clnt); +#endif /* DEBUG */ +} + + +void +calc_minmax_prog_1(char *host, int sock) +{ + CLIENT *clnt; + struct minmax *result_1; + arg_arr calc_minmax_1_arg; + int i, *np, *arrp; + +#ifndef DEBUG + clnt = clnt_create(host, calc_minmax_PROG, calc_minmax_VERS, "netpath"); + if (clnt == (CLIENT *) NULL) { + clnt_pcreateerror(host); + exit(1); + } +#endif /* DEBUG */ + + np = &calc_minmax_1_arg.n; + + if (recv(sock, np, sizeof(int), 0) < 0) + goto fail; + calc_minmax_1_arg.arr.arr_len = *np; + calc_minmax_1_arg.arr.arr_val = emalloc(*np * sizeof(int)); + arrp = calc_minmax_1_arg.arr.arr_val; + + if (recv(sock, arrp, *np * sizeof(int), 0) < 0) + goto fail; + + result_1 = calc_minmax_1(&calc_minmax_1_arg, clnt); + if (result_1 == (struct minmax *) NULL) { + clnt_perror(clnt, "call failed"); + } + + printf("[%s] server response: min: %d\tmax: %d\n", + argv0, result_1->arr.arr_val[0], result_1->arr.arr_val[1]); + if (send(sock, result_1->arr.arr_val, 2 * sizeof(int), 0) < 0) + goto fail; + return; +fail: + fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); + close(sock); + if (arrp != NULL) + free(arrp); +#ifndef DEBUG + clnt_destroy(clnt); +#endif /* DEBUG */ +} + + +void +calc_prod_prog_1(char *host, int sock) +{ + CLIENT *clnt; + struct float_arr *result_1; + arg_prod calc_prod_1_arg; + int i, *np, *arrp; + float *ap; + +#ifndef DEBUG + clnt = clnt_create(host, calc_prod_PROG, calc_prod_VERS, "netpath"); + if (clnt == (CLIENT *) NULL) { + clnt_pcreateerror(host); + exit(1); + } +#endif /* DEBUG */ + + ap = &calc_prod_1_arg.a; + np = &calc_prod_1_arg.arr.n; + + if (recv(sock, ap, sizeof(float), 0) < 0) + goto fail; + if (recv(sock, np, sizeof(int), 0) < 0) + goto fail; + calc_prod_1_arg.arr.arr.arr_len = *np; + calc_prod_1_arg.arr.arr.arr_val = emalloc(*np * sizeof(int)); + arrp = calc_prod_1_arg.arr.arr.arr_val; + + if (recv(sock, arrp, *np * sizeof(int), 0) < 0) + goto fail; + + result_1 = calc_prod_1(&calc_prod_1_arg, clnt); + if (result_1 == (struct float_arr *) NULL) { + clnt_perror(clnt, "call failed"); + } + + printf("[%s] server response: [", argv0); + for (i = 0; i < calc_prod_1_arg.arr.n; i++) { + printf("%.3f%s", result_1->arr.arr_val[i], + i == calc_prod_1_arg.arr.n - 1 ? "" : ", "); + } + printf("]\n"); + + if (send(sock, result_1->arr.arr_val, *np * sizeof(float), 0) < 0) + goto fail; + return; +fail: + /* we failed... */ + fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); + close(sock); + if (arrp != NULL) + free(arrp); +#ifndef DEBUG + clnt_destroy(clnt); +#endif /* DEBUG */ +} + +static void +serve_client(char *host, int cfd) +{ + int n; + + for (;;) { + /* receive option */ + if (recv(cfd, &n, sizeof(int), 0) < 0) { + fprintf(stderr, "[%s] connection with %d dropped\n", + argv0, cfd); + close(cfd); + _exit(0); + } + switch (n) { + case 1: + calc_avg_prog_1(host, cfd); + break; + case 2: + calc_minmax_prog_1(host, cfd); + break; + case 3: + calc_prod_prog_1(host, cfd); + break; + case 4: + printf("[%s] sock %d disconnected\n", argv0, cfd); + close(cfd); + return; + } + } +} + +static void +sighandler(int sig) +{ + f_quit = 1; +} + +static void * +emalloc(size_t nb) +{ + void *p; + + if ((p = malloc(nb)) == NULL) + err(1, "malloc"); + return (p); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-p port] hostname\n", argv0); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct hostent *hp; + struct sigaction sa; + int backlog = 5; + int port = 9999; + int sfd, cfd; + char *host, ch; + + argv0 = *argv; + while ((ch = getopt(argc, argv, "b:p:")) != -1) { + switch (ch) { + case 'b': + if ((backlog = atoi(optarg)) < 1) + errx(1, "backlog value must be > 1"); + break; + case 'p': + if ((port = atoi(optarg)) < 1024) + errx(1, "can't use port number < 1024"); + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + host = *argv; + + memset(&sa, 0, sizeof(sa)); + sigfillset(&sa.sa_mask); + sa.sa_handler = sighandler; + /* be sensitive to termination signals */ + if (sigaction(SIGINT, &sa, NULL) < 0) + err(1, "sigaction(SIGINT)"); + if (sigaction(SIGTERM, &sa, NULL) < 0) + err(1, "sigaction(SIGTERM)"); + + if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(AF_INET)"); + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = INADDR_ANY; + if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) + err(1, "connect"); + if (listen(sfd, backlog) < 0) + err(1, "listen"); + + for (;;) { + if (f_quit) + break; + + if ((cfd = accept(sfd, NULL, NULL)) < 0) + continue; + printf("[%s] accepted client at sock: %d\n", argv0, cfd); + + switch (fork()) { + case -1: + err(1, "fork"); + case 0: + serve_client(host, cfd); + _exit(0); + default: + close(cfd); + } + + } + close(sfd); + + return (0); +} diff --git a/c_distributed_sys/ex1/rpc_server.c b/c_distributed_sys/ex1/rpc_server.c @@ -0,0 +1,66 @@ +#include <err.h> +#include <stdlib.h> +#include <stdio.h> + +#include "rpc.h" + +static void *emalloc(size_t); + +static void * +emalloc(size_t nb) +{ + void *p; + + if ((p = malloc(nb)) == NULL) + err(1, "malloc"); + return (p); +} + +float * +calc_avg_1_svc(arg_arr *argp, struct svc_req *rqstp) +{ + static float result; + int i, sum; + + for (i = 0, sum = 0; i < argp->n; i++) + sum += argp->arr.arr_val[i]; + result = sum / (float)argp->n; + + return (&result); +} + +struct minmax * +calc_minmax_1_svc(arg_arr *argp, struct svc_req *rqstp) +{ + static struct minmax result; + int i, *min, *max; + + result.arr.arr_len = 2; + result.arr.arr_val = emalloc(2 * sizeof(int)); + min = &result.arr.arr_val[0]; + max = &result.arr.arr_val[1]; + *min = *argp->arr.arr_val; + *max = *argp->arr.arr_val; + for (i = 0; i < argp->n; i++) { + if (argp->arr.arr_val[i] < *min) + *min = argp->arr.arr_val[i]; + if (argp->arr.arr_val[i] > *max) + *max = argp->arr.arr_val[i]; + } + + return (&result); +} + +struct float_arr * +calc_prod_1_svc(arg_prod *argp, struct svc_req *rqstp) +{ + static struct float_arr result; + int i; + + result.arr.arr_len = argp->arr.n; + result.arr.arr_val = emalloc(argp->arr.n * sizeof(float)); + for (i = 0; i < argp->arr.n; i++) + result.arr.arr_val[i] = argp->a * argp->arr.arr.arr_val[i]; + + return (&result); +} diff --git a/c_distributed_sys/ex1/sock_client.c b/c_distributed_sys/ex1/sock_client.c @@ -0,0 +1,210 @@ +#include <sys/socket.h> +#include <sys/types.h> + +#include <arpa/inet.h> +#include <netdb.h> +#include <netinet/in.h> + +#include <err.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static void esend(int, void *, size_t, int); +static void erecv(int, void *, size_t, int); +static void *emalloc(size_t); +static void safe_scanf(void *, char *, char *, ...); +static void calc_avg(int); +static void calc_minmax(int); +static void calc_prod(int); +static void usage(void); + +static char *argv0; + +static void +esend(int fd, void *msg, size_t len, int flags) +{ + if (send(fd, msg, len, flags) < 0) + err(1, "send"); +} + +static void +erecv(int fd, void *msg, size_t len, int flags) +{ + if (recv(fd, msg, len, flags) < 0) + err(1, "recv"); +} + +static void * +emalloc(size_t nb) +{ + void *p; + + if ((p = malloc(nb)) == NULL) + err(1, "malloc"); + return (p); +} + +static void +safe_scanf(void *n, char *type, char *fmt, ...) +{ + va_list ap; + char buf[BUFSIZ]; + int rc; + + do { + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + printf("\r%s", buf); + rc = scanf(type, n); + (void)getchar(); + } while (rc != 1); +} + +static void +calc_avg(int fd) +{ + float res; + int *arr, n, i; + + safe_scanf(&n, "%d", "%s> n: ", argv0); + arr = emalloc(n * sizeof(int)); + for (i = 0; i < n; i++) + safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); + + esend(fd, &n, sizeof(int), 0); + esend(fd, arr, n * sizeof(int), 0); + + erecv(fd, &res, sizeof(float), 0); + printf("[%s] server response: %.3f\n", argv0, res); + + free(arr); +} + +static void +calc_minmax(int fd) +{ + int res[2], *arr, n, i; + + safe_scanf(&n, "%d", "%s> n: ", argv0); + arr = emalloc(n * sizeof(int)); + for (i = 0; i < n; i++) + safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); + + esend(fd, &n, sizeof(int), 0); + esend(fd, arr, n * sizeof(int), 0); + + erecv(fd, &res, 2 * sizeof(int), 0); + printf("[%s] server response: min: %d\tmax: %d\n", + argv0, res[0], res[1]); + + free(arr); +} + +static void +calc_prod(int fd) +{ + float *res, a; + int *arr, n, i; + + safe_scanf(&a, "%f", "%s> a: ", argv0); + safe_scanf(&n, "%d", "%s> n: ", argv0); + arr = emalloc(n * sizeof(int)); + for (i = 0; i < n; i++) + safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); + + esend(fd, &a, sizeof(float), 0); + esend(fd, &n, sizeof(int), 0); + esend(fd, arr, n * sizeof(int), 0); + + res = emalloc(n * sizeof(float)); + erecv(fd, res, n * sizeof(float), 0); + printf("[%s] server response: [", argv0); + for (i = 0; i < n; i++) + printf("%.3f%s", res[i], i == n - 1 ? "" : ", "); + printf("]\n"); + + free(arr); + free(res); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-p port] hostname\n", argv0); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct hostent *hp; + int port = 9999; + int fd, n; + char *host, ch; + + argv0 = *argv; + while ((ch = getopt(argc, argv, "p:")) != -1) { + switch (ch) { + case 'p': + if ((port = atoi(optarg)) < 1024) + errx(1, "can't use port number < 1024"); + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + host = *argv; + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(AF_INET)"); + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + if (!inet_aton(host, &sin.sin_addr)) { + if ((hp = gethostbyname(host)) == NULL) + errx(1, "gethostbyname(%s) failed", host); + (void)memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); + } + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) + err(1, "connect"); + + for (;;) { + printf("1: average\n2: min and max\n3: product\n4: disconnect\n"); + safe_scanf(&n, "%d", "%s> your choice: ", argv0); + + switch (n) { + case 1: + esend(fd, &n, sizeof(int), 0); + calc_avg(fd); + break; + case 2: + esend(fd, &n, sizeof(int), 0); + calc_minmax(fd); + break; + case 3: + esend(fd, &n, sizeof(int), 0); + calc_prod(fd); + break; + case 4: + esend(fd, &n, sizeof(int), 0); + goto end; + default: + printf("[%s] invalid choice\n", argv0); + } + } +end: + close(fd); + + return (0); +}