root/tags/5.4.pre05/wxis_src/xis_server.c

Revision 1, 22.7 kB (checked in by heitor.barbieri, 4 years ago)

Criação do svn para Cisis.

Line 
1/*
2..Server program that makes a connection for a byte stream socket in the
3Internet namespace.
4..Once it has connected to the server, it sends a text string to the server and
5gets the response.
6Returns 0 or a negative error value.
7*/
8/*
916.9.7 Byte Stream Connection Server Example
10The server end is much more complicated. Since we want to allow multiple clients
11to be connected to the server at the same time, it would be incorrect to wait
12for input from a single client by simply calling read or recv. Instead, the
13right thing to do is to use select (see Waiting for I/O) to wait for input on
14all of the open sockets. This also allows the server to deal with additional
15connection requests.
16
17This particular server doesn't do anything interesting once it has gotten a
18message from a client. It does close the socket for that client when it detects
19an end-of-file condition (resulting from the client shutting down its end of the
20connection).
21This program uses make_socket to set up the socket address; see Inet Example.
22*/
23
24#define GEN_MAIN 1
25
26#if GEN_MAIN
27     #include <stdio.h>
28     #include <errno.h>
29     #include <stdlib.h>
30     #include <string.h>
31     #include <unistd.h>
32     #include <sys/types.h>
33#endif /*  GEN_MAIN */
34
35     #include <sys/socket.h>
36     #include <netinet/in.h>
37     #include <netdb.h>
38     #include <time.h>
39     #include <setjmp.h>
40     #include <fcntl.h>
41     #include <sys/types.h>
42     #include <sys/stat.h>
43
44     #include "xis_server.h"
45     #include "cisis.h"
46     //#include "chronometer.h"
47
48#if GEN_MAIN
49     #define BUFFERSIZE    2097152 //51200
50#endif /*  GEN_MAIN */
51
52     #define REPLYSIZE     1048576 //51200
53     #define MAXCONNQUEUED 30
54
55
56/*----------------------------------------------------------------------------*/
57     int mainFunc(int argc,       /* wxis main function */
58                  char *argv[],
59                  char *envv[],
60                  OUT_BUFFER *outBuff);
61
62     void wxisMainFunc(int   argc,     /* quantity of arguments */
63                       char *argv[],    /* array of arguments */
64                       char *envv[],    /* array of environment variables */
65                       OUT_BUFFER *outBuff);  /* string output of wxis */
66
67     int xis_mainserver_make_socket (uint16_t port,
68                                     int trace);
69     int xis_mainserver_read_from_client (uint16_t port,
70                                          int filedes,
71                                          char *buffer,
72                                          int buffersize,
73                                          int trace);
74     int xis_mainserver_write_to_client (uint16_t port,
75                                         int filedes,
76                                         char *message,
77                                         int messagesize,
78                                         int trace);
79     int xis_mainserver (char *envv[],
80                         uint16_t port,
81                         char *buffer,
82                         int buffersize,
83                         OUT_BUFFER *outBuff,
84                         int maxconnqueued,
85                         int trace);
86
87/*----------------------------------------------------------------------------*/
88extern int     fatal_errcod;    /* cisis fatal() error code */
89extern char    fatal_iomsg[];   /* cisis fatal() flag/msg */
90extern jmp_buf fatal_jumper;    /* cisis fatal() longjmp() */
91extern int     dbxopt_errno;    /* dbxopen() - dbname/errno msg before fatal */
92/*----------------------------------------------------------------------------*/
93
94    void clearBuff(OUT_BUFFER *outBuff) {
95        if (outBuff) {
96            outBuff->freeSize = outBuff->totalSize;
97            outBuff->textSize = 0;
98            if (outBuff->buffer) {
99                outBuff->buffer[0] = '\0';
100            }
101        }
102    }
103
104    int writeBuff(char *mess,
105                  OUT_BUFFER *outBuff,
106                  int append) {
107        int msize = (mess ? strlen(mess) : 0);
108        int osize = 0;
109        int maxsize = outBuff->totalSize;
110
111        if (!mess) {
112            return 0;
113        }
114        if (!outBuff) {
115            return 0;
116        }
117
118        if (!append) {
119            clearBuff(outBuff);
120        }
121
122        osize = outBuff->textSize + msize;
123
124        if (msize >= outBuff->freeSize) {
125            maxsize = (osize > maxsize) ? (2 * osize) : (2 * maxsize);
126            maxsize = (maxsize < 32768 ? 32768 : maxsize);
127            outBuff->buffer = (char *)realloc(outBuff->buffer, maxsize);
128            outBuff->totalSize = maxsize;
129            if (!outBuff->buffer) {
130                outBuff->totalSize = 0;
131                outBuff->freeSize = 0;
132                outBuff->textSize = 0;
133                return 0;
134            }
135        }
136
137        if (append) {
138            outBuff->freeSize = outBuff->totalSize - osize - 1;
139            outBuff->textSize = osize;
140            strcat(outBuff->buffer, mess);
141        } else {
142            outBuff->freeSize = outBuff->totalSize - msize - 1;
143            outBuff->textSize = msize;
144            strcpy(outBuff->buffer, mess);
145        }
146
147        return msize;
148    }
149
150    int checkFileName(char *buffer) {
151        char *p = buffer;
152        int handle;
153        int ret = 0;
154
155        if (buffer) {
156            while(*p) {
157                if (*p == ' ') {
158                    p++;
159                } else {
160                    break;
161                }
162            }
163            if (*p) {
164                if (*p == '@') {
165                    ret = 1;
166                    handle = open(++p, O_RDONLY);
167                    if (handle == -1) {
168                        buffer[0] = '\0';
169                    }
170                    if (read(handle, buffer, BUFFERSIZE) == -1) {
171                        buffer[0] = '\0';
172                    }
173                    close(handle);
174                }
175            }
176        }
177
178        return ret;
179   }
180
181   int writeToFile(char *fname,
182                   OUT_BUFFER *outBuff) {
183        int handle;
184
185        if ((!fname) || (!outBuff)) {
186            return -1;
187        }
188        handle = open(fname, O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
189        if (handle == -1) {
190            return -1;
191        }
192
193        if (outBuff->textSize > 0) {
194            if (write(handle, outBuff->buffer, outBuff->textSize) == -1) {
195                return -1;
196            }
197        }
198        close(handle);
199
200        return 0;
201    }
202
203    int xis_mainserver_make_socket (uint16_t port,
204                                    int trace) {
205        int sock;
206        struct sockaddr_in name;
207
208        /* Create the socket. */
209        sock = socket (PF_INET, SOCK_STREAM, 0);
210        if (sock < 0) {
211            if (trace) {
212                fprintf(stderr, "xis_mainserver_make_socket/socket < 0 \n");
213            }
214            return -1;
215        }
216
217        /* Give the socket a name. */
218        name.sin_family = AF_INET;
219        name.sin_port = htons (port);
220        name.sin_addr.s_addr = htonl (INADDR_ANY);
221        if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
222            if (trace) {
223                fprintf(stderr, "xis_mainserver_make_socket/bind < 0 \n");
224            }
225            return -2;
226        }
227
228        return sock;
229    }
230
231    int xis_mainserver_write_to_client(uint16_t port,
232                                       int filedes,
233                                       char *message,
234                                       int messagesize,
235                                       int trace) {
236        int nbytes;
237                               /* yyyymmdd hh:mm:ss WDAY YDAY */
238        char timestamp[80];    /* 123456789012345678901234 7  8 901 */
239        long secs_now;
240        struct tm *tp;
241
242        time(&secs_now);
243        tp = localtime(&secs_now);
244
245        sprintf(timestamp,"%04d%02d%02d %02d%02d%02d %1d %3d", 1900+tp->tm_year,
246                tp->tm_mon+1,tp->tm_mday, tp->tm_hour,tp->tm_min,tp->tm_sec,
247                tp->tm_wday,tp->tm_yday);
248
249        if (trace) {
250            fprintf (stderr,
251                  "xis_server [%d] [%d] [%s]: reply message (%d bytes): '%s'\n",
252                  port, filedes, timestamp, messagesize, message);
253        }
254
255        nbytes = write (filedes, message, messagesize);
256        if (nbytes < messagesize) {
257            if (trace) {
258                fprintf (stderr, "xis_mainserver_write_to_client/write \n");
259            }
260            return -1;
261        }
262
263        return nbytes;
264    }
265
266    int xis_mainserver_read_from_client(uint16_t port,
267                                        int filedes,
268                                        char *buffer,
269                                        int buffersize,
270                                        int trace) {
271        int nbytes;
272
273        buffer[0]='\0';
274
275        nbytes = read (filedes, buffer, buffersize-1);
276        if (nbytes < 0) {
277            if (trace) {
278                fprintf (stderr, "xis_mainserver_read_from_client/read \n");
279            }
280            return -2;
281        }
282
283        if (trace) {
284            char *p = buffer;
285            int loop = nbytes;
286
287            fprintf (stderr, "xis_mainserver_read_from_client/read(%d): ",
288                                                                     nbytes);
289            for (; loop--; p++) {
290                fprintf (stderr, "%c=%02x ", *p, (int)*p);
291            }
292            fprintf (stderr, "\n");
293        }
294
295        /* EOF (nbytes=0) or Data read. */
296        buffer[nbytes]='\0';
297
298        return nbytes;
299     }
300
301/*
302     xis_mainserver
303*/
304    int xis_mainserver(char *envv[],
305                       uint16_t port,
306                       char *buffer,
307                       int buffersize,
308                       OUT_BUFFER *outBuff,
309                       int maxconnqueued,
310                       int trace) {
311
312        int sock;
313        fd_set active_fd_set, read_fd_set;
314        int i;
315        struct sockaddr_in clientname;
316        size_t size;
317                               /* yyyymmdd hh:mm:ss WDAY YDAY */
318        char timestamp[80];    /* 123456789012345678901234 7  8 901 */
319        long secs_in;
320        long secs_now;
321        struct tm *tp;
322
323        /* Create the socket and set it up to accept connections. */
324        sock = xis_mainserver_make_socket (port, trace);
325
326        time(&secs_now);
327        tp=localtime(&secs_now);
328        secs_in=secs_now;
329
330        sprintf(timestamp,"%04d%02d%02d %02d%02d%02d %1d %3d",
331               1900+tp->tm_year,tp->tm_mon+1,tp->tm_mday, tp->tm_hour,
332               tp->tm_min,tp->tm_sec, tp->tm_wday,tp->tm_yday);
333
334        if (trace) {
335            fprintf (stderr, "xis_server [%d] [%d] [%s] [%d]: got socket \n",
336                     port, sock, timestamp, maxconnqueued);
337        }
338
339        /* <== at most 1 connection queued */
340        if (listen (sock, maxconnqueued) < 0) {
341            if (trace) {
342                fprintf (stderr, "xis_mainserver/listen < 0 \n");
343            }
344            return -1;
345        }
346
347        /* Initialize the set of active sockets. */
348        FD_ZERO (&active_fd_set);
349        FD_SET (sock, &active_fd_set);
350
351        while (1) {
352            /* Block until input arrives on one or more active sockets. */
353            read_fd_set = active_fd_set;
354            if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
355                if (trace) {
356                    fprintf (stderr, "xis_mainserver/select < 0 \n");
357                }
358                return -2;
359            }
360
361            /* Service all the sockets with input pending. */
362            for (i = 0; i < FD_SETSIZE; ++i) {
363                if (FD_ISSET (i, &read_fd_set)) {
364                    if (i == sock) {
365
366                        /* Connection request on original socket. */
367                        int new;
368                        size = sizeof (clientname);
369
370                        new = accept (sock,
371                                      (struct sockaddr *) &clientname,
372                                      &size);
373                        if (new < 0) {
374                            if (trace) {
375                                fprintf (stderr,
376                                                "xis_mainserver/accept < 0 \n");
377                            }
378                            return -3;
379                        }
380
381                        if (trace) {
382                            fprintf (stderr,
383                                     "xis_server [%d] [%d] [%s]: connect from host %s, port %hd \n",
384                                     port, sock, timestamp,
385                                     inet_ntoa (clientname.sin_addr),
386                                     ntohs (clientname.sin_port));
387                        }
388
389                        FD_SET (new, &active_fd_set);
390
391                    } else {
392                        char ** argv = NULL;
393                        int argc = 0;
394                        int c = 0;
395                        int len = 0;
396                        int nbytes = 0;
397                        int isFile = 0;
398
399                        /* Data arriving on an already-connected socket. */
400                        int nread = 0;
401
402                        nread = xis_mainserver_read_from_client (port, i,
403                                                    buffer, buffersize, trace);
404                        time(&secs_now);
405                        tp=localtime(&secs_now);
406
407                        sprintf(timestamp,"%04d%02d%02d %02d%02d%02d %1d %3d",
408                                    1900+tp->tm_year,tp->tm_mon+1,tp->tm_mday,
409                                    tp->tm_hour,tp->tm_min,tp->tm_sec,
410                                    tp->tm_wday,tp->tm_yday);
411
412                        if (trace) {
413                            fprintf (stderr,
414                                     "xis_server [%d] [%d] [%s]: got message (%d bytes): '%s' \n",
415                                     port, sock, timestamp, nread, buffer);
416                        }
417
418                        len = strlen(buffer);
419                        if (len == 0) {
420                            writeBuff("xis_server 100 eof msg\n", outBuff, 0); /* never */
421                        } else if (strcmp(buffer,"\n") == 0) {
422                            writeBuff("xis_server 101 null msg\n", outBuff, 0);
423                        } else if (strcmp(buffer + nread - 1,"\n") != 0) {
424                            writeBuff("xis_server 505 bad msg\n", outBuff, 0);
425                        } else {
426                            while(--len >= 0) {
427                                if ((buffer[len] == '\n') ||
428                                    (buffer[len] == '\r')) {
429                                    buffer[len] = 0x00;
430                                } else {
431                                    break;
432                                }
433                            }
434                            isFile = checkFileName(buffer);
435                            if (buffer[0] == '\0') {
436                                writeBuff("xis_server invalid input msg\n", outBuff, 0);
437                            } else {
438                                argc = createArgv(buffer, &argv);
439                                if (trace) {
440                                    for (c = 0; c < argc; c++) {
441                                        if (argv[c] == NULL) {
442                                            printf("argv[%d]=NULL\n", c);
443                                        } else {
444                                            printf("argv[%d]=[%s]\n", c, argv[c]);
445                                        }
446                                    }
447                                }
448
449                                clearBuff(outBuff);
450
451                                wxisMainFunc(argc, argv, envv, outBuff);
452
453                                for (c = 0; c < argc; c++) {
454                                     free(argv[c]);
455                                     argv[c] = NULL;
456                                }
457                                free(argv);
458                            }
459                        }
460                        /* Response */
461                        if (isFile) {
462                            writeToFile("/home/scielo/www/htdocs/xis_server.out", outBuff);
463                            clearBuff(outBuff);
464                            writeBuff("@/home/scielo/www/htdocs/xis_server.out", outBuff, 0);
465                        }
466                        if (outBuff->textSize > 0) {
467                            nbytes = xis_mainserver_write_to_client (port, i, outBuff->buffer,
468                                                                 outBuff->textSize, trace);
469                            if (nbytes < 0) {
470                                if (trace) {
471                                    fprintf (stderr,
472                                             "xis_mainserver/write error=%d\n",
473                                             nbytes);
474                                }
475                            }
476                        }
477                        clearBuff(outBuff);
478                        close (i);
479                        FD_CLR (i, &active_fd_set);
480
481                    } /* end data read */
482                } /* end if FD_ISSET */
483            } /* end for FD_SETSIZE */
484        } /* end while */
485
486        /* Release the socket. */
487        close (sock);
488
489        time(&secs_now);
490        tp=localtime(&secs_now);
491
492        if (trace) {
493            sprintf(timestamp, "%04d%02d%02d %02d%02d%02d %1d %3d",
494                    1900+tp->tm_year,tp->tm_mon+1,tp->tm_mday, tp->tm_hour,
495                    tp->tm_min,tp->tm_sec, tp->tm_wday,tp->tm_yday);
496            fprintf(stderr,
497                    "xis_server [%d] [%d] [%s]: close socket (%ld seconds) \n",
498                    port, sock, timestamp,secs_now-secs_in);
499        }
500
501        return 0;
502    } /* end of xis_mainserver */
503
504    void wxisMainFunc(int   argc,      /* quantity of arguments */
505                      char *argv[],    /* array of arguments */
506                      char *envv[],    /* array of environment variables */
507                      OUT_BUFFER *outBuff) { /* string output of wxis */
508        int     z_xerrno;
509        int     z_errcod;
510        char    z_iomsg[80];
511        jmp_buf z_jumper;
512        int     z_jumprc;
513
514        /* save/notrap */
515        strcpy(z_iomsg,fatal_iomsg);
516        memcpy(z_jumper,fatal_jumper,sizeof(fatal_jumper));
517        z_errcod = fatal_errcod;
518        z_xerrno = dbxopt_errno;
519
520        /* trap cisis fatal() */
521        strcpy(fatal_iomsg,"trap");
522
523        /* disable dbxopen msg */
524        dbxopt_errno=0;
525        z_jumprc = setjmp(fatal_jumper);
526
527        if (z_jumprc == 0) {
528            mainFunc(argc, argv, envv, outBuff);
529        } else { /* error */
530            char aux[256];
531            sprintf(aux, "\nWXIS|error|%s\n", fatal_iomsg);
532            writeBuff(aux, outBuff, 0);
533        }
534
535        /* restore/notrap */
536         memcpy(fatal_jumper,z_jumper,sizeof(fatal_jumper));
537         strcpy(fatal_iomsg,z_iomsg);
538         fatal_errcod = z_errcod;
539         dbxopt_errno = z_xerrno;
540     }
541
542    int createArgv(char *in,
543                   char ***argv) {
544        int argc = 0;
545        int max = 40;
546        int size = max * sizeof(char *);
547        char *aux = NULL;
548        int pos = 0;
549        char **tokens = NULL;
550
551        if (in != NULL) {
552            tokens = malloc(size);
553            memset(tokens, 0x00, size);
554            tokens[argc++] = strdup("wxis_server");
555            aux = malloc(strlen(in));
556
557            while((argc < max) && (*in != 0x00)) {
558                pos = 0;
559
560                while(*in == ' ') {
561                    in++;
562                }
563                if (*in == 0x00) {
564                    break;
565                }
566                if (*in == '"') {
567                    in++;
568                    while(1) {
569                        if ((*in == 0x00) || (*in == '"')) {
570                            aux[pos] = 0x00;
571                            tokens[argc++] = strdup(aux);
572                            if (*in != 0x00) {
573                                in++;
574                            }
575                            break;
576                        }
577                        aux[pos++] = *in;
578                        in++;
579                    }
580                } else {
581                    while(1) {
582                        if ((*in == 0x00) || (*in == ' ')) {
583                            aux[pos] = 0x00;
584                            tokens[argc++] = strdup(aux);
585                            if (*in != 0x00) {
586                                in++;
587                            }
588                            break;
589                        }
590                        aux[pos++] = *in;
591                        in++;
592                    }
593                }
594            }
595            free(aux);
596        }
597        *argv = tokens;
598/*{
599int c = 0;
600for (c=0; c<argc; c++) {
601    printf("argv[%d]=%s\n", c, tokens[c]);
602    printf("argv[%d]=%s\n", c, argv[0][c]);
603}
604}*/
605        return argc;
606    }
607
608#if GEN_MAIN
609    int main(int argc,
610             char *argv[],
611             char *envv[]) {
612
613        /* calling parameters */
614        int port = 0;
615        int rc = 0;
616        int trace = 0;
617
618        char buffer[BUFFERSIZE];
619
620        /* Create the global output buffer */
621        OUT_BUFFER outBuff;
622
623        outBuff.totalSize = 50000;
624        outBuff.freeSize = 50000;
625        outBuff.textSize = 0;
626        outBuff.buffer = malloc(50000);
627        outBuff.buffer[0] = '\0';
628
629        //chrono_init("chrono_wxis_server.txt");
630
631        if (argc == 1) {
632            fprintf(stderr, "xis_server port=<PORT> [trace] \n");
633            exit (EXIT_FAILURE);
634        }
635
636        if (strncmp(argv[1], "port=", 5) != 0) {
637            fprintf(stderr, "xis_server port=<PORT> [trace] \n");
638            exit (EXIT_FAILURE);
639        }
640
641        port = atoi(argv[1] + 5);
642        if (port <= 0) {
643            fprintf(stderr, "xis_server port [%d] <= 0\n", port);
644            exit (EXIT_FAILURE);
645        }
646
647        if (argc > 2) {
648            if (strcmp(argv[2], "trace") == 0) {
649                trace = 1;
650            } else {
651                fprintf(stderr, "xis_server port=<PORT> [trace] \n");
652                exit (EXIT_FAILURE);
653            }
654        }
655
656        if (trace) {
657            char *div = "-----------------------------------------------------------------------------\n";
658
659            argc = createArgv("what", &argv);
660            fprintf(stderr, div);
661            wxisMainFunc(argc, argv, envv, &outBuff);
662            if (outBuff.buffer) {
663                fprintf(stderr, outBuff.buffer);
664            }
665            fprintf(stderr, "xis_server: %d \n", port);
666        }
667
668        rc = xis_mainserver(envv, (uint16_t)port, buffer,
669                            BUFFERSIZE, &outBuff, MAXCONNQUEUED, trace);
670
671        if (outBuff.buffer) {
672            free(outBuff.buffer);
673        }
674
675        //chrono_end();
676
677        if (rc < 0) {
678            if (trace) {
679                fprintf(stderr, "xis_server: exit_failure %d \n", rc);
680            }
681            exit (EXIT_FAILURE);
682        }
683
684        if (trace) {
685            fprintf(stderr, "xis_server: exit_success \n");
686        }
687
688        exit (EXIT_SUCCESS);
689    }
690#endif /*  GEN_MAIN */
691
692#undef GEN_MAIN
Note: See TracBrowser for help on using the browser.