|
|
The following code represents the connection-mode server program described in ``Advanced programming example''. This server manages multiple connect indications in an event-driven manner. Either connection-mode client presented earlier will communicate with this server.
#include <xti.h> #include <fcntl.h> #include <stdio.h> #include <poll.h> #include <stropts.h> #include <signal.h>#define NUM_FDS 1 #define MAX_CONN_IND 4 #define SRV_ADDR 1 /* server's well known address */
int conn_fd; /* server connection here */
/* holds connect indications */ struct t_call *calls[NUM_FDS][MAX_CONN_IND];
main() { struct pollfd pollfds[NUM_FDS]; struct t_bind *bind; int i;
/* * Only opening and binding one transport endpoint, * but more could be supported */ if ((pollfds[0].fd = t_open("/dev/ticots", 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 t_bind structure failed"); exit(2); } bind->qlen = MAX_CONN_IND; bind->addr.len = sizeof(int); *(int *)bind->addr.buf = SRV_ADDR;
if (t_bind(pollfds[0].fd, bind, NULL) < 0) { t_error("t_bind failed"); exit(3); }
pollfds[0].events = POLLIN;
while (1) { 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 returned error event"); exit(6); 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);
case T_ERROR: fprintf(stderr,"t_look returned T_ERROR event\n"); exit(8);
case -1: t_error("t_look failed"); exit(9);
case 0: /* since POLLIN returned, this should not happen */ fprintf(stderr,"t_look returned no event\n"); exit(10);
case T_LISTEN: /* * find free element in calls array */ 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 call ind in array and delete it */ 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/ticots", O_RDWR, NULL)) < 0) { t_error("open failed"); exit(14); } if (t_bind(conn_fd, NULL, NULL) < 0) { t_error("t_bind failed"); exit(15); }
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); } }
connrelease() { /* conn_fd is global because needed here */ if (t_look(conn_fd) == T_DISCONNECT) { fprintf(stderr, "connection aborted\n"); exit(12); }
/* else orderly release indication - normal exit */ exit(0); }
run_server(listen_fd) int listen_fd; { int nbytes; FILE *logfp; /* file pointer to log file */ char buf[1024];
switch (fork()) {
case -1: perror("fork failed"); exit(20);
default: /* parent */
/* close conn_fd and then go up and listen again */ if (t_close(conn_fd) < 0) { t_error("t_close failed for conn_fd"); exit(21); } return;
case 0: /* child */
/* close listen_fd and do service */ if (t_close(listen_fd) < 0) { t_error("t_close failed for listen_fd"); exit(22); } if ((logfp = fopen("logfile", "r")) == NULL) { perror("cannot open logfile"); exit(23); }
signal(SIGPOLL, connrelease); if (ioctl(conn_fd, I_SETSIG, S_INPUT) < 0) { perror("ioctl I_SETSIG failed"); exit(24); } if (t_look(conn_fd) != 0) { /* disconnect already there? */ 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); } pause(); /* until orderly release indication arrives */ } }