Loading...
Select Version
&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);
}
}