|
|
The following code represents the connection-mode server program described in ``Connection-mode service''. This server establishes a transport connection with a client, and then transfers a log file to the client on the other side of the connection. The connection is released using the orderly release facility of the Transport Interface. The connection-mode client presented earlier will communicate with this server.
#include <xti.h> #include <stropts.h> #include <fcntl.h> #include <stdio.h> #include <signal.h>#define DISCONNECT (-1) #define SRV_ADDR 1 /* server's well known address */
int conn_fd; /* connection established here */
main() { int listen_fd; /* listening transport endpoint */ struct t_bind *bind; struct t_call *call;
if ((listen_fd = t_open("/dev/ticots", O_RDWR, NULL)) < 0) { t_error("t_open failed for listen_fd"); exit(1); }
/* * By assuming that the address is an integer value, * this program may not run over another protocol. */ if ((bind = (struct t_bind *)t_alloc(listen_fd, T_BIND, T_ALL)) == NULL) { t_error("t_alloc of t_bind structure failed"); exit(2); } bind->qlen = 1; bind->addr.len = sizeof(int); *(int *)bind->addr.buf = SRV_ADDR;
if (t_bind(listen_fd, bind, NULL) < 0) { t_error("t_bind failed for listen_fd"); exit(3); }
if ((call = (struct t_call *)t_alloc(listen_fd, T_CALL, T_ALL)) == NULL) { t_error("t_alloc of t_call structure failed"); exit(5); }
while (1) { if (t_listen(listen_fd, call) < 0) { t_error("t_listen failed for listen_fd"); exit(6); }
if ((conn_fd = accept_call(listen_fd, call)) != DISCONNECT) run_server(listen_fd); } }
accept_call(listen_fd, call) int listen_fd; struct t_call *call; { int resfd;
if ((resfd = t_open("/dev/ticots", O_RDWR, NULL)) < 0) { t_error("t_open for responding fd failed"); exit(7); }
if (t_bind(resfd, NULL, NULL) < 0) { t_error("t_bind for responding fd failed"); exit(8); }
if (t_accept(listen_fd, resfd, call) < 0) { if (t_errno == TLOOK) { /* must be a disconnect */ if (t_rcvdis(listen_fd, NULL) < 0) { t_error("t_rcvdis failed for listen_fd"); exit(9); } if (t_close(resfd) < 0) { t_error("t_close failed for responding fd"); exit(10); } /* go back up and listen for other calls */ return(DISCONNECT); } t_error("t_accept failed"); exit(11); } return(resfd); }
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) { /* was disconnect 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 */ } }