uni

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

rpc_client.c (6431B)


      1 #include <sys/socket.h>
      2 #include <sys/types.h>
      3 
      4 #include <arpa/inet.h>
      5 #include <netdb.h>
      6 #include <netinet/in.h>
      7 
      8 #include <err.h>
      9 #include <signal.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <unistd.h>
     14 
     15 #include "rpc.h"
     16 
     17 static void	serve_client(char *, int);
     18 static void	sighandler(int);
     19 static void	*emalloc(size_t);
     20 static void	usage(void);
     21 
     22 static char	*argv0;
     23 /* becomes true when a termination signal is caught */
     24 static volatile sig_atomic_t f_quit = 0;
     25 
     26 void
     27 calc_avg_prog_1(char *host, int sock)
     28 {
     29 	CLIENT *clnt;
     30 	float  *result_1;
     31 	arg_arr  calc_avg_1_arg;
     32 	int *np, *arrp;
     33 
     34 #ifndef	DEBUG
     35 	clnt = clnt_create(host, calc_avg_PROG, calc_avg_VERS, "netpath");
     36 	if (clnt == (CLIENT *) NULL) {
     37 		clnt_pcreateerror(host);
     38 		exit(1);
     39 	}
     40 #endif	/* DEBUG */
     41 	
     42 	/* avoid typing all this */
     43 	np = &calc_avg_1_arg.n;
     44 
     45 	/* receive number of elements */
     46 	if (recv(sock, np, sizeof(int), 0) < 0)
     47 		goto fail;
     48 	calc_avg_1_arg.arr.arr_len = *np;
     49 	calc_avg_1_arg.arr.arr_val = emalloc(*np * sizeof(int));
     50 	arrp = calc_avg_1_arg.arr.arr_val;
     51 
     52 	/* receive array */
     53 	if (recv(sock, arrp, *np * sizeof(int), 0) < 0)
     54 		goto fail;
     55 
     56 	/* make RPC */
     57 	result_1 = calc_avg_1(&calc_avg_1_arg, clnt);
     58 	if (result_1 == (float *) NULL) {
     59 		clnt_perror(clnt, "call failed");
     60 	}
     61 
     62 	/* send results back to sock_client */
     63 	printf("[%s] sock: %d\tserver response: avg: %.3f\n", argv0, sock, *result_1);
     64 	if (send(sock, result_1, sizeof(float), 0) < 0)
     65 		goto fail;
     66 	return;
     67 fail:
     68 	/* we failed... */
     69 	fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock);
     70 	close(sock);
     71 	if (arrp != NULL)
     72 		free(arrp);
     73 #ifndef	DEBUG
     74 	clnt_destroy(clnt);
     75 #endif		/* DEBUG */
     76 }
     77 
     78 
     79 void
     80 calc_minmax_prog_1(char *host, int sock)
     81 {
     82 	CLIENT *clnt;
     83 	struct minmax  *result_1;
     84 	arg_arr  calc_minmax_1_arg;
     85 	int i, *np, *arrp;
     86 
     87 #ifndef	DEBUG
     88 	clnt = clnt_create(host, calc_minmax_PROG, calc_minmax_VERS, "netpath");
     89 	if (clnt == (CLIENT *) NULL) {
     90 		clnt_pcreateerror(host);
     91 		exit(1);
     92 	}
     93 #endif	/* DEBUG */
     94 
     95 	np = &calc_minmax_1_arg.n;
     96 
     97 	if (recv(sock, np, sizeof(int), 0) < 0)
     98 		goto fail;
     99 	calc_minmax_1_arg.arr.arr_len = *np;
    100 	calc_minmax_1_arg.arr.arr_val = emalloc(*np * sizeof(int));
    101 	arrp = calc_minmax_1_arg.arr.arr_val;
    102 
    103 	if (recv(sock, arrp, *np * sizeof(int), 0) < 0)
    104 		goto fail;
    105 
    106 	result_1 = calc_minmax_1(&calc_minmax_1_arg, clnt);
    107 	if (result_1 == (struct minmax *) NULL) {
    108 		clnt_perror(clnt, "call failed");
    109 	}
    110 
    111 	printf("[%s] server response: min: %d\tmax: %d\n",
    112 	    argv0, result_1->arr.arr_val[0], result_1->arr.arr_val[1]);
    113 	if (send(sock, result_1->arr.arr_val, 2 * sizeof(int), 0) < 0)
    114 		goto fail;
    115 	return;
    116 fail:
    117 	fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock);
    118 	close(sock);
    119 	if (arrp != NULL)
    120 		free(arrp);
    121 #ifndef	DEBUG
    122 	clnt_destroy(clnt);
    123 #endif		/* DEBUG */
    124 }
    125 
    126 
    127 void
    128 calc_prod_prog_1(char *host, int sock)
    129 {
    130 	CLIENT *clnt;
    131 	struct float_arr  *result_1;
    132 	arg_prod  calc_prod_1_arg;
    133 	int i, *np, *arrp;
    134 	float *ap;
    135 
    136 #ifndef	DEBUG
    137 	clnt = clnt_create(host, calc_prod_PROG, calc_prod_VERS, "netpath");
    138 	if (clnt == (CLIENT *) NULL) {
    139 		clnt_pcreateerror(host);
    140 		exit(1);
    141 	}
    142 #endif	/* DEBUG */
    143 
    144 	ap = &calc_prod_1_arg.a;
    145 	np = &calc_prod_1_arg.arr.n;
    146 
    147 	if (recv(sock, ap, sizeof(float), 0) < 0)
    148 		goto fail;
    149 	if (recv(sock, np, sizeof(int), 0) < 0)
    150 		goto fail;
    151 	calc_prod_1_arg.arr.arr.arr_len = *np;
    152 	calc_prod_1_arg.arr.arr.arr_val = emalloc(*np * sizeof(int));
    153 	arrp = calc_prod_1_arg.arr.arr.arr_val;
    154 
    155 	if (recv(sock, arrp, *np * sizeof(int), 0) < 0)
    156 		goto fail;
    157 
    158 	result_1 = calc_prod_1(&calc_prod_1_arg, clnt);
    159 	if (result_1 == (struct float_arr *) NULL) {
    160 		clnt_perror(clnt, "call failed");
    161 	}
    162 
    163 	printf("[%s] server response: [", argv0);
    164 	for (i = 0; i < calc_prod_1_arg.arr.n; i++) {
    165 		printf("%.3f%s", result_1->arr.arr_val[i],
    166 		    i == calc_prod_1_arg.arr.n - 1 ? "" : ", ");
    167 	}
    168 	printf("]\n");
    169 
    170 	if (send(sock, result_1->arr.arr_val, *np * sizeof(float), 0) < 0)
    171 		goto fail;
    172 	return;
    173 fail:
    174 	/* we failed... */
    175 	fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock);
    176 	close(sock);
    177 	if (arrp != NULL)
    178 		free(arrp);
    179 #ifndef	DEBUG
    180 	clnt_destroy(clnt);
    181 #endif		/* DEBUG */
    182 }
    183 
    184 static void
    185 serve_client(char *host, int cfd)
    186 {
    187 	int n;
    188 
    189 	for (;;) {
    190 		/* receive option */
    191 		if (recv(cfd, &n, sizeof(int), 0) < 0) {
    192 			fprintf(stderr, "[%s] connection with %d dropped\n",
    193 			    argv0, cfd);
    194 			close(cfd);
    195 			_exit(0);
    196 		}
    197 		switch (n) {
    198 		case 1:
    199 			calc_avg_prog_1(host, cfd);
    200 			break;
    201 		case 2:
    202 			calc_minmax_prog_1(host, cfd);
    203 			break;
    204 		case 3:
    205 			calc_prod_prog_1(host, cfd);
    206 			break;
    207 		case 4:
    208 			printf("[%s] sock %d disconnected\n", argv0, cfd);
    209 			close(cfd);
    210 			return;
    211 		}
    212 	}
    213 }
    214 
    215 static void
    216 sighandler(int sig)
    217 {
    218 	f_quit = 1;
    219 }
    220 
    221 static void *
    222 emalloc(size_t nb)
    223 {
    224 	void *p;
    225 
    226 	if ((p = malloc(nb)) == NULL)
    227 		err(1, "malloc");
    228 	return (p);
    229 }
    230 
    231 static void
    232 usage(void)
    233 {
    234 	fprintf(stderr, "usage: %s [-p port] hostname\n", argv0);
    235 	exit(0);
    236 }
    237 
    238 int
    239 main(int argc, char *argv[])
    240 {
    241 	struct sockaddr_in sin;
    242 	struct hostent *hp;
    243 	struct sigaction sa;
    244 	int backlog = 5;
    245 	int port = 9999;
    246 	int sfd, cfd;
    247 	char *host, ch;
    248 
    249 	argv0 = *argv;
    250 	while ((ch = getopt(argc, argv, "b:p:")) != -1) {
    251 		switch (ch) {
    252 		case 'b':
    253 			if ((backlog = atoi(optarg)) < 1)
    254 				errx(1, "backlog value must be > 1");
    255 			break;
    256 		case 'p':
    257 			if ((port = atoi(optarg)) < 1024)
    258 				errx(1, "can't use port number < 1024");
    259 			break;
    260 		case '?':
    261 		default:
    262 			usage();
    263 		}
    264 	}
    265 	argc -= optind;
    266 	argv += optind;
    267 
    268 	if (argc < 1)
    269 		usage();
    270 	host = *argv;
    271 
    272 	memset(&sa, 0, sizeof(sa));
    273 	sigfillset(&sa.sa_mask);
    274 	sa.sa_handler = sighandler;
    275 	/* be sensitive to termination signals */
    276 	if (sigaction(SIGINT, &sa, NULL) < 0)
    277 		err(1, "sigaction(SIGINT)");
    278 	if (sigaction(SIGTERM, &sa, NULL) < 0)
    279 		err(1, "sigaction(SIGTERM)");
    280 
    281 	if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    282 		err(1, "socket(AF_INET)");
    283 	memset(&sin, 0, sizeof(sin));
    284 	sin.sin_family = AF_INET;
    285 	sin.sin_port = htons(port);
    286 	sin.sin_addr.s_addr = INADDR_ANY;
    287 	if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    288 		err(1, "connect");
    289 	if (listen(sfd, backlog) < 0)
    290 		err(1, "listen");
    291 
    292 	for (;;) {
    293 		if (f_quit)
    294 			break;
    295 
    296 		if ((cfd = accept(sfd, NULL, NULL)) < 0)
    297 			continue;
    298 		printf("[%s] accepted client at sock: %d\n", argv0, cfd);
    299 
    300 		switch (fork()) {
    301 		case -1:
    302 			err(1, "fork");
    303 		case 0:
    304 			serve_client(host, cfd);
    305 			_exit(0);
    306 		default:
    307 			close(cfd);
    308 		}
    309 
    310 	}
    311 	close(sfd);
    312 
    313 	return (0);
    314 }