Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Event-controlled server

&pagelevel(3)&pagelevel

The following server program for the connection-oriented service is described in detail in section "Advanced XTI(POSIX) concepts". The server manages several connection requests in an event-controlled manner. All of the connection-oriented clients described earlier in this chapter can communicate with this server.

#include <xti.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define FILENAME "/etc/services"
#define NUM_FDS 1
#define MAX_CONN_IND 4
#define SRV_ADDR 0x7F000001
#define SRV_PORT 8888
int conn_fd; /* Connection to server */
/* For storing the connections */
struct t_call *calls[NUM_FDS][MAX_CONN_IND];
main()
{
   struct pollfd pollfds[NUM_FDS];
   struct t_bind *bind;
   struct sockaddr_in *sin;
   int i;
   /*
    * Only open and bind one transport endpoint,
    * although it would also be possible for more
    */
   if ((pollfds[0].fd = t_open("/dev/tcp", O_RDWR, NULL)) < 0) {
      t_error("t_open() failed");
      exit(1);
   }
   if ((bind = (struct t_bind *)t_alloc(pollfds[0].fd,
                                            T_BIND, T_ALL)) == NULL) {
      t_error("t_alloc() of the t_bind structure failed");
      exit(2);
   }
   bind->qlen = MAX_CONN_IND;
   bind->addr.len=sizeof(struct sockaddr_in);
   sin=(struct sockaddr_in *)bind->addr.buf;
   sin->sin_family=AF_INET;
   sin->sin_port=htons(SRV_PORT);
   sin->sin_addr.s_addr=htonl(SRV_ADDR);
   if (t_bind(pollfds[0].fd, bind, bind) < 0) {
      t_error("t_bind() failed");
      exit(3);
   }
   pollfds[0].events = POLLIN;
   for(;;) {
      if (poll(pollfds, NUM_FDS, -1) < 0) {
         perror("poll() failed");
         exit(5);
      }
      for (i = 0; i < NUM_FDS; i++) {
         switch (pollfds[i].revents) {
         default:
                 perror(
                 "Poll returns error event");
                 exit(6);
                 break;
         case 0:
                 continue;
         case POLLIN:
                 do_event(i, pollfds[i].fd);
                 service_conn_ind(i, pollfds[i].fd);
         }
      }
   }
}
do_event(slot, fd)
{
   struct t_discon *discon;
   int i; 
   switch (t_look(fd)) {
   default:
      fprintf(stderr,"t_look: unexpected event\n");
      exit(7);
      break;
   case -1:
      t_error("t_look() failed");
      exit(9);
      break;
   case 0:
       /* If POLLIN is returned, this should not happen */
       fprintf(stderr,"No event returned from t_look()\n");
       exit(10);
   case T_LISTEN:
      /*
       * Find free member in call area
       */
      for (i = 0; i < MAX_CONN_IND; i++) {
         if (calls[slot][i] == NULL)
             break;
      }
      if ((calls[slot][i] = (struct t_call *)t_alloc(fd, 
                                            T_CALL, T_ALL)) == NULL) {
         t_error("t_alloc() of t_call structure failed");
         exit(11);
      }
      if (t_listen(fd, calls[slot][i]) < 0) {
         t_error("t_listen() failed");
         exit(12);
      }
      break;
   case T_DISCONNECT:
      discon = (struct t_discon *)t_alloc(fd, T_DIS, T_ALL);
      if (t_rcvdis(fd, discon) < 0) {
         t_error("t_rcvdis() failed");
         exit(13);
      }
      /*
       * Find and delete ind call in area
       */
      for (i = 0; i < MAX_CONN_IND; i++) {
         if (discon->sequence == calls[slot][i]->sequence) {
            t_free(calls[slot][i], T_CALL);
            calls[slot][i] = NULL;
         }
      }
      t_free(discon, T_DIS);
      break;
   }
}
service_conn_ind(slot, fd)
{
   int i;
   for (i = 0; i < MAX_CONN_IND; i++) {
      if (calls[slot][i] == NULL)
         continue;
      if ((conn_fd = t_open("/dev/tcp", O_RDWR, NULL)) < 0) {
         t_error("t_open() failed");
         exit(14);
      }
      if (t_accept(fd, conn_fd, calls[slot][i]) < 0) {
         if (t_errno == TLOOK) {
              t_close(conn_fd);
              return;
         }
         t_error("t_accept() failed");
         exit(16);
      }
      t_free(calls[slot][i], T_CALL);
      calls[slot][i] = NULL;
      run_server(fd);
   }
}
run_server(listen_fd)
int listen_fd;
{
   int nbytes;
   FILE *logfp; /* Pointer to log file */
   char buf[1024];
   switch (fork()) {
   case -1:
      perror("fork() failed");
      exit(20);
      break;
   default: /* Parent process */
      /* Close conn_fd and monitor again */
      if (t_close(conn_fd) < 0) {
         t_error("t_close() failed for conn_fd");
         exit(21);
      }
      return;
   case 0:  /* Child process */
      /* Close listen_fd and execute service */
      if (t_close(listen_fd) < 0) {
         t_error("t_close() failed for listen_fd");
         exit(22);
      }
      if ((logfp = fopen(FILENAME, "r")) == NULL) {
         perror("Log file cannot be opened");
         exit(23);
      }
      if (t_look(conn_fd) != 0) { /* Is there already a disconnect? */
         fprintf(stderr, "t_look: unexpected event\n");
         exit(25);
      }
      while ((nbytes = fread(buf, 1, 1024, logfp)) > 0)
         if (t_snd(conn_fd, buf, nbytes, 0) < 0) {
             t_error("t_snd() failed");
             exit(26);
         }
      if (t_sndrel(conn_fd) < 0) {
         t_error("t_sndrel() failed");
         exit(27);
      }
      while(t_look(conn_fd) == 0) {
         sleep(1);
      }
      if(t_look(conn_fd) == T_DISCONNECT) {
         fprintf(stderr, "Connection aborted\n");
         exit(12);
      }
      exit(0);
   }
}