xref: /csrg-svn/usr.bin/tn3270/api/api_exch.c (revision 31890)
1*31890Sminshall /*
2*31890Sminshall  *	Copyright (c) 1984-1987 by the Regents of the
3*31890Sminshall  *	University of California and by Gregory Glenn Minshall.
4*31890Sminshall  *
5*31890Sminshall  *	Permission to use, copy, modify, and distribute these
6*31890Sminshall  *	programs and their documentation for any purpose and
7*31890Sminshall  *	without fee is hereby granted, provided that this
8*31890Sminshall  *	copyright and permission appear on all copies and
9*31890Sminshall  *	supporting documentation, the name of the Regents of
10*31890Sminshall  *	the University of California not be used in advertising
11*31890Sminshall  *	or publicity pertaining to distribution of the programs
12*31890Sminshall  *	without specific prior permission, and notice be given in
13*31890Sminshall  *	supporting documentation that copying and distribution is
14*31890Sminshall  *	by permission of the Regents of the University of California
15*31890Sminshall  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16*31890Sminshall  *	University of California nor Gregory Glenn Minshall make
17*31890Sminshall  *	representations about the suitability of this software
18*31890Sminshall  *	for any purpose.  It is provided "as is" without
19*31890Sminshall  *	express or implied warranty.
20*31890Sminshall  */
21*31890Sminshall 
22*31890Sminshall #ifndef lint
23*31890Sminshall static char sccsid[] = "@(#)api_exch.c	1.8 (Berkeley) 07/17/87";
24*31890Sminshall #endif	/* not lint */
25*31890Sminshall 
2631460Sminshall #include <stdio.h>
2731460Sminshall 
2831801Sminshall #include "../general/general.h"
2931801Sminshall 
3031460Sminshall #include "api_exch.h"
3131460Sminshall 
3231467Sminshall static int sock;		/* Socket number */
3331467Sminshall 
3431474Sminshall static char whoarewe[40] = "";
3531493Sminshall #define	WHO_ARE_WE()	fprintf(stderr, "(API %s) ", whoarewe);
3631474Sminshall 
3731493Sminshall static enum {CONTENTION, SEND, RECEIVE } conversation;
3831493Sminshall 
3931493Sminshall static struct exch_exch exch_state;
4031493Sminshall 
4131493Sminshall static unsigned int
4231493Sminshall     my_sequence,
4331493Sminshall     your_sequence;
4431493Sminshall 
4531499Sminshall static char ibuffer[4000], *ibuf_next, *ibuf_last;
4631460Sminshall #define	IBUFADDED(i)		ibuf_last += (i)
4731499Sminshall #define	IBUFAVAILABLE()		(ibuf_last-ibuf_next)
4831460Sminshall #define	IBUFFER()		ibuffer
4931499Sminshall #define	IBUFFREE()		(ibuffer+sizeof ibuffer-ibuf_last-1)
5031493Sminshall #define	IBUFGETBYTES(w,l)	{ memcpy(w, ibuf_next, l); ibuf_next += l; }
5131460Sminshall #define	IBUFRESET()		(ibuf_next = ibuf_last = ibuffer)
5231460Sminshall 
5331499Sminshall char obuffer[4000], *obuf_next;
5431460Sminshall #define	OBUFADDBYTES(w,l)	{ memcpy(obuf_next, w, l); obuf_next += l; }
5531460Sminshall #define	OBUFAVAILABLE()		(obuf_next - obuffer)
5631460Sminshall #define	OBUFFER()		obuffer
5731460Sminshall #define	OBUFRESET()		obuf_next = obuffer
5831460Sminshall #define	OBUFROOM()		(obuffer+sizeof obuffer-obuf_next)
5931460Sminshall 
6031460Sminshall 
6131460Sminshall static int
6231460Sminshall outflush()
6331460Sminshall {
6431460Sminshall     int length = OBUFAVAILABLE();
6531460Sminshall 
6631460Sminshall     if (length != 0) {
6731460Sminshall 	if (write(sock, OBUFFER(), length) != length) {
6831493Sminshall 	    WHO_ARE_WE();
6931474Sminshall 	    perror("write");
7031460Sminshall 	    return -1;
7131460Sminshall 	}
7231460Sminshall 	OBUFRESET();
7331460Sminshall     }
7431460Sminshall     return 0;				/* All OK */
7531460Sminshall }
7631460Sminshall 
7731460Sminshall 
7831460Sminshall static int
7931499Sminshall iget(location, length)
8031499Sminshall char	*location;
8131499Sminshall int	length;
8231460Sminshall {
8331460Sminshall     int i;
8431499Sminshall     int count;
8531460Sminshall 
8631460Sminshall     if (OBUFAVAILABLE()) {
8731460Sminshall 	if (outflush() == -1) {
8831460Sminshall 	    return -1;
8931460Sminshall 	}
9031460Sminshall     }
9131499Sminshall     if ((count = IBUFAVAILABLE()) != 0) {
9231499Sminshall 	if (count > length) {
9331499Sminshall 	    count = length;
9431499Sminshall 	}
9531499Sminshall 	IBUFGETBYTES(location, count);
9631499Sminshall 	length -= count;
9731499Sminshall 	location += count;
9831460Sminshall     }
9931499Sminshall     while (length) {
10031499Sminshall 	if (ibuf_next == ibuf_last) {
10131499Sminshall 	    IBUFRESET();
10231499Sminshall 	}
10331499Sminshall 	if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) {
10431493Sminshall 	    WHO_ARE_WE();
10531474Sminshall 	    perror("read");
10631460Sminshall 	    return -1;
10731460Sminshall 	}
10831499Sminshall 	if (count == 0) {
10931474Sminshall 	    /* Reading past end-of-file */
11031493Sminshall 	    WHO_ARE_WE();
11131493Sminshall 	    fprintf(stderr, "End of file read\r\n");
11231474Sminshall 	    return -1;
11331474Sminshall 	}
11431499Sminshall 	IBUFADDED(count);
11531499Sminshall 	if (count > length) {
11631499Sminshall 	    count = length;
11731499Sminshall 	}
11831499Sminshall 	IBUFGETBYTES(location, count);
11931499Sminshall 	length -= count;
12031499Sminshall 	location += count;
12131460Sminshall     }
12231460Sminshall     return 0;
12331460Sminshall }
12431460Sminshall 
12531493Sminshall static char *
12631493Sminshall exch_to_ascii(exch)
12731493Sminshall int exch;			/* opcode to decode */
12831493Sminshall {
12931493Sminshall     switch (exch) {
13031493Sminshall     case EXCH_EXCH_COMMAND:
13131493Sminshall 	return "Command";
13231493Sminshall     case EXCH_EXCH_TYPE:
13331493Sminshall 	return "Type";
13431493Sminshall     case EXCH_EXCH_TURNAROUND:
13531493Sminshall 	return "Turnaround";
13631493Sminshall     case EXCH_EXCH_RTS:
13731493Sminshall 	return "Request to Send";
13831493Sminshall     default:
13931493Sminshall 	{
14031493Sminshall 	    static char unknown[40];
14131493Sminshall 
14231493Sminshall 	    sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff);
14331493Sminshall 	    return unknown;
14431493Sminshall 	}
14531493Sminshall     }
14631493Sminshall }
14731493Sminshall 
14831493Sminshall /*
14931493Sminshall  * Send the exch structure, updating the sequnce number field.
15031493Sminshall  */
15131493Sminshall 
15231493Sminshall static int
15331493Sminshall send_state()
15431493Sminshall {
15531493Sminshall     if (OBUFROOM() < sizeof exch_state) {
15631493Sminshall 	if (outflush() == -1) {
15731493Sminshall 	    return -1;
15831493Sminshall 	}
15931493Sminshall     }
16031498Sminshall     my_sequence = (my_sequence+1)&0xff;
16131498Sminshall     exch_state.my_sequence = my_sequence;
16231493Sminshall     exch_state.your_sequence = your_sequence;
16331493Sminshall     OBUFADDBYTES((char *)&exch_state, sizeof exch_state);
16431493Sminshall     return 0;
16531493Sminshall }
16631493Sminshall 
16731493Sminshall /*
16831493Sminshall  * Receive the exch structure from the other side, checking
16931493Sminshall  * sequence numbering.
17031493Sminshall  */
17131493Sminshall 
17231493Sminshall static int
17331493Sminshall receive_state()
17431493Sminshall {
17531499Sminshall     if (iget((char *)&exch_state, sizeof exch_state) == -1) {
17631499Sminshall 	return -1;
17731493Sminshall     }
17831493Sminshall     if (conversation != CONTENTION) {
17931493Sminshall 	if (exch_state.your_sequence != my_sequence) {
18031493Sminshall 	    WHO_ARE_WE();
18131493Sminshall 	    fprintf(stderr, "Send sequence number mismatch.\n");
18231493Sminshall 	    return -1;
18331493Sminshall 	}
18431498Sminshall 	if (exch_state.my_sequence != ((++your_sequence)&0xff)) {
18531493Sminshall 	    WHO_ARE_WE();
18631493Sminshall 	    fprintf(stderr, "Receive sequence number mismatch.\n");
18731493Sminshall 	    return -1;
18831493Sminshall 	}
18931493Sminshall     }
19031498Sminshall     your_sequence = exch_state.my_sequence;
19131493Sminshall     return 0;
19231493Sminshall }
19331493Sminshall 
19431493Sminshall static int
19531493Sminshall enter_receive()
19631493Sminshall {
19731493Sminshall     switch (conversation) {
19831493Sminshall     case CONTENTION:
19931493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
20031493Sminshall 	if (send_state() == -1) {
20131493Sminshall 	    return -1;
20231493Sminshall 	}
20331493Sminshall 	if (receive_state() == -1) {
20431493Sminshall 	    return -1;
20531493Sminshall 	}
20631493Sminshall 	if (exch_state.opcode != EXCH_EXCH_RTS) {
20731493Sminshall 	    WHO_ARE_WE();
20831493Sminshall 	    fprintf(stderr, "In CONTENTION state:  ");
20931493Sminshall 	    if (exch_state.opcode == EXCH_EXCH_TURNAROUND) {
21031493Sminshall 		fprintf(stderr,
21131493Sminshall 		    "Both sides tried to enter RECEIVE state.\n");
21231493Sminshall 	    } else {
21331493Sminshall 		fprintf(stderr,
21431493Sminshall 		    "Protocol error trying to enter RECEIVE state.\n");
21531493Sminshall 	    }
21631493Sminshall 	    return -1;
21731493Sminshall 	}
21831493Sminshall 	break;
21931493Sminshall     case SEND:
22031493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
22131493Sminshall 	if (send_state() == -1) {
22231493Sminshall 	    return -1;
22331493Sminshall 	}
22431493Sminshall 	break;
22531493Sminshall     }
22631493Sminshall     conversation = RECEIVE;
22731493Sminshall     return 0;
22831493Sminshall }
22931493Sminshall 
23031493Sminshall static int
23131493Sminshall enter_send()
23231493Sminshall {
23331493Sminshall     switch (conversation) {
23431493Sminshall     case CONTENTION:
23531493Sminshall 	exch_state.opcode = EXCH_EXCH_RTS;
23631493Sminshall 	if (send_state() == -1) {
23731493Sminshall 	    return -1;
23831493Sminshall 	}
23931493Sminshall 	 /* fall through */
24031493Sminshall     case RECEIVE:
24131493Sminshall 	if (receive_state() == -1) {
24231493Sminshall 	    return -1;
24331493Sminshall 	}
24431493Sminshall 	if (exch_state.opcode != EXCH_EXCH_TURNAROUND) {
24531493Sminshall 	    WHO_ARE_WE();
24631493Sminshall 	    fprintf(stderr, "Conversation error - both sides in SEND state.\n");
24731493Sminshall 	    return -1;
24831493Sminshall 	}
24931493Sminshall     }
25031493Sminshall     conversation = SEND;
25131493Sminshall     return 0;
25231493Sminshall }
25331493Sminshall 
25431467Sminshall int
25531493Sminshall api_exch_nextcommand()
25631467Sminshall {
25731493Sminshall     if (conversation != RECEIVE) {
25831493Sminshall 	if (enter_receive() == -1) {
25931467Sminshall 	    return -1;
26031467Sminshall 	}
26131467Sminshall     }
26231493Sminshall     if (receive_state() == -1) {
26331493Sminshall 	return -1;
26431493Sminshall     }
26531493Sminshall     if (exch_state.opcode != EXCH_EXCH_COMMAND) {
26631493Sminshall 	WHO_ARE_WE();
26731493Sminshall 	fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n",
26831493Sminshall 	    exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode));
26931493Sminshall 	return -1;
27031493Sminshall     }
27131493Sminshall     return exch_state.command_or_type;
27231467Sminshall }
27331467Sminshall 
27431467Sminshall 
27531467Sminshall int
27631460Sminshall api_exch_incommand(command)
27731460Sminshall int command;
27831460Sminshall {
27931460Sminshall     int i;
28031460Sminshall 
28131493Sminshall     if ((i = api_exch_nextcommand()) == -1) {
28231493Sminshall 	return -1;
28331460Sminshall     }
28431460Sminshall     if (i != command) {
28531493Sminshall 	WHO_ARE_WE();
28631460Sminshall 	fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n",
28731460Sminshall 				command, i);
28831460Sminshall 	return -1;
28931460Sminshall     }
29031460Sminshall     return 0;
29131460Sminshall }
29231460Sminshall 
29331460Sminshall 
29431467Sminshall int
29531460Sminshall api_exch_outcommand(command)
29631460Sminshall int command;
29731460Sminshall {
29831493Sminshall     if (conversation != SEND) {
29931493Sminshall 	if (enter_send() == -1) {
30031460Sminshall 	    return -1;
30131460Sminshall 	}
30231460Sminshall     }
30331493Sminshall     exch_state.command_or_type = command;
30431493Sminshall     exch_state.opcode = EXCH_EXCH_COMMAND;
30531493Sminshall     if (send_state() == -1) {
30631493Sminshall 	return -1;
30731493Sminshall     } else {
30831493Sminshall 	return 0;
30931493Sminshall     }
31031460Sminshall }
31131460Sminshall 
31231460Sminshall 
31331467Sminshall int
31431460Sminshall api_exch_outtype(type, length, location)
31531460Sminshall int
31631460Sminshall     type,
31731460Sminshall     length;
31831460Sminshall char
31931460Sminshall     *location;
32031460Sminshall {
32131801Sminshall     int netleng = length;
32231460Sminshall 
32331493Sminshall     if (conversation != SEND) {
32431493Sminshall 	if (enter_send() == -1) {
32531460Sminshall 	    return -1;
32631460Sminshall 	}
32731460Sminshall     }
32831493Sminshall     exch_state.opcode = EXCH_EXCH_TYPE;
32931493Sminshall     exch_state.command_or_type = type;
33031493Sminshall     exch_state.length = netleng;
33131493Sminshall     if (send_state() == -1) {
33231493Sminshall 	return -1;
33331493Sminshall     }
33431493Sminshall     if (length) {
33531493Sminshall 	if (OBUFROOM() > length) {
33631493Sminshall 	    OBUFADDBYTES(location, length);
33731493Sminshall 	} else {
33831493Sminshall 	    if (outflush() == -1) {
33931493Sminshall 		return -1;
34031493Sminshall 	    }
34131493Sminshall 	    if (write(sock, location, length) != length) {
34231493Sminshall 		WHO_ARE_WE();
34331493Sminshall 		perror("write");
34431493Sminshall 		return -1;
34531493Sminshall 	    }
34631460Sminshall 	}
34731460Sminshall     }
34831493Sminshall     return 0;
34931460Sminshall }
35031460Sminshall 
35131460Sminshall 
35231467Sminshall int
35331460Sminshall api_exch_intype(type, length, location)
35431460Sminshall int
35531460Sminshall     type,
35631460Sminshall     length;
35731460Sminshall char
35831460Sminshall     *location;
35931460Sminshall {
36031801Sminshall     int i, netleng = length;
36131460Sminshall 
36231493Sminshall     if (conversation != RECEIVE) {
36331493Sminshall 	if (enter_receive() == -1) {
36431460Sminshall 	    return -1;
36531460Sminshall 	}
36631460Sminshall     }
36731493Sminshall     if (receive_state() == -1) {
36831460Sminshall 	return -1;
36931460Sminshall     }
37031493Sminshall     if (exch_state.opcode != EXCH_EXCH_TYPE) {
37131493Sminshall 	WHO_ARE_WE();
37231493Sminshall 	fprintf(stderr,
37331493Sminshall 	    "Expected to receive a %s exchange, received a %s exchange.\n",
37431493Sminshall 	    exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode));
37531493Sminshall 	return -1;
37631493Sminshall     }
37731493Sminshall     if (exch_state.command_or_type != type) {
37831493Sminshall 	WHO_ARE_WE();
37931493Sminshall 	fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n",
38031493Sminshall 	    type, exch_state.command_or_type);
38131493Sminshall 	return -1;
38231493Sminshall     }
38331493Sminshall     if (exch_state.length != netleng) {
38431460Sminshall 	fprintf(stderr, "Type 0x%x - expected length %d, received length %d.\n",
38531801Sminshall 		type, length, exch_state.length);
38631460Sminshall 	return -1;
38731460Sminshall     }
38831499Sminshall     if (iget(location, length) == -1) {
38931499Sminshall 	return -1;
39031460Sminshall     }
39131460Sminshall     return 0;
39231460Sminshall }
39331467Sminshall 
39431467Sminshall int
39531493Sminshall api_exch_flush()
39631493Sminshall {
39731493Sminshall     return outflush();
39831493Sminshall }
39931493Sminshall 
40031493Sminshall int
40131474Sminshall api_exch_init(sock_number, ourname)
40231467Sminshall int sock_number;
40331474Sminshall char *ourname;
40431467Sminshall {
40531467Sminshall     sock = sock_number;
40631474Sminshall     strcpy(whoarewe, ourname);		/* For error messages */
40731467Sminshall 
40831493Sminshall     my_sequence = your_sequence = 0;
40931493Sminshall 
41031493Sminshall     conversation = CONTENTION;		/* We don't know which direction */
41131493Sminshall 
41231467Sminshall     IBUFRESET();
41331467Sminshall     OBUFRESET();
41431467Sminshall 
41531467Sminshall     return 0;
41631467Sminshall }
417