xref: /csrg-svn/usr.bin/tn3270/api/api_exch.c (revision 62317)
148754Sbostic /*-
2*62317Sbostic  * Copyright (c) 1988, 1993
3*62317Sbostic  *	The Regents of the University of California.  All rights reserved.
431890Sminshall  *
548754Sbostic  * %sccs.include.redist.c%
631890Sminshall  */
731890Sminshall 
831890Sminshall #ifndef lint
9*62317Sbostic static char sccsid[] = "@(#)api_exch.c	8.1 (Berkeley) 06/06/93";
1033820Sbostic #endif /* not lint */
1131890Sminshall 
1231460Sminshall #include <stdio.h>
1331460Sminshall 
1431801Sminshall #include "../general/general.h"
1531801Sminshall 
1631460Sminshall #include "api_exch.h"
1731460Sminshall 
1831467Sminshall static int sock;		/* Socket number */
1931467Sminshall 
2031474Sminshall static char whoarewe[40] = "";
2131493Sminshall #define	WHO_ARE_WE()	fprintf(stderr, "(API %s) ", whoarewe);
2231474Sminshall 
2331493Sminshall static enum {CONTENTION, SEND, RECEIVE } conversation;
2431493Sminshall 
2531493Sminshall static struct exch_exch exch_state;
2631493Sminshall 
2731493Sminshall static unsigned int
2831493Sminshall     my_sequence,
2931493Sminshall     your_sequence;
3031493Sminshall 
3131499Sminshall static char ibuffer[4000], *ibuf_next, *ibuf_last;
3231460Sminshall #define	IBUFADDED(i)		ibuf_last += (i)
3331499Sminshall #define	IBUFAVAILABLE()		(ibuf_last-ibuf_next)
3431460Sminshall #define	IBUFFER()		ibuffer
3531499Sminshall #define	IBUFFREE()		(ibuffer+sizeof ibuffer-ibuf_last-1)
3631493Sminshall #define	IBUFGETBYTES(w,l)	{ memcpy(w, ibuf_next, l); ibuf_next += l; }
3731460Sminshall #define	IBUFRESET()		(ibuf_next = ibuf_last = ibuffer)
3831460Sminshall 
3931499Sminshall char obuffer[4000], *obuf_next;
4031460Sminshall #define	OBUFADDBYTES(w,l)	{ memcpy(obuf_next, w, l); obuf_next += l; }
4131460Sminshall #define	OBUFAVAILABLE()		(obuf_next - obuffer)
4231460Sminshall #define	OBUFFER()		obuffer
4331460Sminshall #define	OBUFRESET()		obuf_next = obuffer
4431460Sminshall #define	OBUFROOM()		(obuffer+sizeof obuffer-obuf_next)
4531460Sminshall 
4631460Sminshall 
4731460Sminshall static int
outflush()4831460Sminshall outflush()
4931460Sminshall {
5031460Sminshall     int length = OBUFAVAILABLE();
5131460Sminshall 
5231460Sminshall     if (length != 0) {
5331460Sminshall 	if (write(sock, OBUFFER(), length) != length) {
5431493Sminshall 	    WHO_ARE_WE();
5531474Sminshall 	    perror("write");
5631460Sminshall 	    return -1;
5731460Sminshall 	}
5831460Sminshall 	OBUFRESET();
5931460Sminshall     }
6031460Sminshall     return 0;				/* All OK */
6131460Sminshall }
6231460Sminshall 
6331460Sminshall 
6431460Sminshall static int
iget(location,length)6531499Sminshall iget(location, length)
6631499Sminshall char	*location;
6731499Sminshall int	length;
6831460Sminshall {
6931499Sminshall     int count;
7031460Sminshall 
7131460Sminshall     if (OBUFAVAILABLE()) {
7231460Sminshall 	if (outflush() == -1) {
7331460Sminshall 	    return -1;
7431460Sminshall 	}
7531460Sminshall     }
7631499Sminshall     if ((count = IBUFAVAILABLE()) != 0) {
7731499Sminshall 	if (count > length) {
7831499Sminshall 	    count = length;
7931499Sminshall 	}
8031499Sminshall 	IBUFGETBYTES(location, count);
8131499Sminshall 	length -= count;
8231499Sminshall 	location += count;
8331460Sminshall     }
8431499Sminshall     while (length) {
8531499Sminshall 	if (ibuf_next == ibuf_last) {
8631499Sminshall 	    IBUFRESET();
8731499Sminshall 	}
8831499Sminshall 	if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) {
8931493Sminshall 	    WHO_ARE_WE();
9031474Sminshall 	    perror("read");
9131460Sminshall 	    return -1;
9231460Sminshall 	}
9331499Sminshall 	if (count == 0) {
9431474Sminshall 	    /* Reading past end-of-file */
9531493Sminshall 	    WHO_ARE_WE();
9631493Sminshall 	    fprintf(stderr, "End of file read\r\n");
9731474Sminshall 	    return -1;
9831474Sminshall 	}
9931499Sminshall 	IBUFADDED(count);
10031499Sminshall 	if (count > length) {
10131499Sminshall 	    count = length;
10231499Sminshall 	}
10331499Sminshall 	IBUFGETBYTES(location, count);
10431499Sminshall 	length -= count;
10531499Sminshall 	location += count;
10631460Sminshall     }
10731460Sminshall     return 0;
10831460Sminshall }
10931460Sminshall 
11031493Sminshall static char *
exch_to_ascii(exch)11131493Sminshall exch_to_ascii(exch)
11231493Sminshall int exch;			/* opcode to decode */
11331493Sminshall {
11431493Sminshall     switch (exch) {
11531493Sminshall     case EXCH_EXCH_COMMAND:
11631493Sminshall 	return "Command";
11731493Sminshall     case EXCH_EXCH_TYPE:
11831493Sminshall 	return "Type";
11931493Sminshall     case EXCH_EXCH_TURNAROUND:
12031493Sminshall 	return "Turnaround";
12131493Sminshall     case EXCH_EXCH_RTS:
12231493Sminshall 	return "Request to Send";
12331493Sminshall     default:
12431493Sminshall 	{
12531493Sminshall 	    static char unknown[40];
12631493Sminshall 
12731493Sminshall 	    sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff);
12831493Sminshall 	    return unknown;
12931493Sminshall 	}
13031493Sminshall     }
13131493Sminshall }
13231493Sminshall 
13331493Sminshall /*
13431493Sminshall  * Send the exch structure, updating the sequnce number field.
13531493Sminshall  */
13631493Sminshall 
13731493Sminshall static int
send_state()13831493Sminshall send_state()
13931493Sminshall {
14031493Sminshall     if (OBUFROOM() < sizeof exch_state) {
14131493Sminshall 	if (outflush() == -1) {
14231493Sminshall 	    return -1;
14331493Sminshall 	}
14431493Sminshall     }
14531498Sminshall     my_sequence = (my_sequence+1)&0xff;
14631498Sminshall     exch_state.my_sequence = my_sequence;
14731493Sminshall     exch_state.your_sequence = your_sequence;
14831493Sminshall     OBUFADDBYTES((char *)&exch_state, sizeof exch_state);
14931493Sminshall     return 0;
15031493Sminshall }
15131493Sminshall 
15231493Sminshall /*
15331493Sminshall  * Receive the exch structure from the other side, checking
15431493Sminshall  * sequence numbering.
15531493Sminshall  */
15631493Sminshall 
15731493Sminshall static int
receive_state()15831493Sminshall receive_state()
15931493Sminshall {
16031499Sminshall     if (iget((char *)&exch_state, sizeof exch_state) == -1) {
16131499Sminshall 	return -1;
16231493Sminshall     }
16331493Sminshall     if (conversation != CONTENTION) {
16431493Sminshall 	if (exch_state.your_sequence != my_sequence) {
16531493Sminshall 	    WHO_ARE_WE();
16631493Sminshall 	    fprintf(stderr, "Send sequence number mismatch.\n");
16731493Sminshall 	    return -1;
16831493Sminshall 	}
16931498Sminshall 	if (exch_state.my_sequence != ((++your_sequence)&0xff)) {
17031493Sminshall 	    WHO_ARE_WE();
17131493Sminshall 	    fprintf(stderr, "Receive sequence number mismatch.\n");
17231493Sminshall 	    return -1;
17331493Sminshall 	}
17431493Sminshall     }
17531498Sminshall     your_sequence = exch_state.my_sequence;
17631493Sminshall     return 0;
17731493Sminshall }
17831493Sminshall 
17931493Sminshall static int
enter_receive()18031493Sminshall enter_receive()
18131493Sminshall {
18231493Sminshall     switch (conversation) {
18331493Sminshall     case CONTENTION:
18431493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
18531493Sminshall 	if (send_state() == -1) {
18631493Sminshall 	    return -1;
18731493Sminshall 	}
18831493Sminshall 	if (receive_state() == -1) {
18931493Sminshall 	    return -1;
19031493Sminshall 	}
19131493Sminshall 	if (exch_state.opcode != EXCH_EXCH_RTS) {
19231493Sminshall 	    WHO_ARE_WE();
19331493Sminshall 	    fprintf(stderr, "In CONTENTION state:  ");
19431493Sminshall 	    if (exch_state.opcode == EXCH_EXCH_TURNAROUND) {
19531493Sminshall 		fprintf(stderr,
19631493Sminshall 		    "Both sides tried to enter RECEIVE state.\n");
19731493Sminshall 	    } else {
19831493Sminshall 		fprintf(stderr,
19931493Sminshall 		    "Protocol error trying to enter RECEIVE state.\n");
20031493Sminshall 	    }
20131493Sminshall 	    return -1;
20231493Sminshall 	}
20331493Sminshall 	break;
20431493Sminshall     case SEND:
20531493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
20631493Sminshall 	if (send_state() == -1) {
20731493Sminshall 	    return -1;
20831493Sminshall 	}
20931493Sminshall 	break;
21031493Sminshall     }
21131493Sminshall     conversation = RECEIVE;
21231493Sminshall     return 0;
21331493Sminshall }
21431493Sminshall 
21531493Sminshall static int
enter_send()21631493Sminshall enter_send()
21731493Sminshall {
21831493Sminshall     switch (conversation) {
21931493Sminshall     case CONTENTION:
22031493Sminshall 	exch_state.opcode = EXCH_EXCH_RTS;
22131493Sminshall 	if (send_state() == -1) {
22231493Sminshall 	    return -1;
22331493Sminshall 	}
22431493Sminshall 	 /* fall through */
22531493Sminshall     case RECEIVE:
22631493Sminshall 	if (receive_state() == -1) {
22731493Sminshall 	    return -1;
22831493Sminshall 	}
22931493Sminshall 	if (exch_state.opcode != EXCH_EXCH_TURNAROUND) {
23031493Sminshall 	    WHO_ARE_WE();
23131493Sminshall 	    fprintf(stderr, "Conversation error - both sides in SEND state.\n");
23231493Sminshall 	    return -1;
23331493Sminshall 	}
23431493Sminshall     }
23531493Sminshall     conversation = SEND;
23631493Sminshall     return 0;
23731493Sminshall }
23831493Sminshall 
23931467Sminshall int
api_exch_nextcommand()24031493Sminshall api_exch_nextcommand()
24131467Sminshall {
24231493Sminshall     if (conversation != RECEIVE) {
24331493Sminshall 	if (enter_receive() == -1) {
24431467Sminshall 	    return -1;
24531467Sminshall 	}
24631467Sminshall     }
24731493Sminshall     if (receive_state() == -1) {
24831493Sminshall 	return -1;
24931493Sminshall     }
25031493Sminshall     if (exch_state.opcode != EXCH_EXCH_COMMAND) {
25131493Sminshall 	WHO_ARE_WE();
25231493Sminshall 	fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n",
25331493Sminshall 	    exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode));
25431493Sminshall 	return -1;
25531493Sminshall     }
25631493Sminshall     return exch_state.command_or_type;
25731467Sminshall }
25831467Sminshall 
25931467Sminshall 
26031467Sminshall int
api_exch_incommand(command)26131460Sminshall api_exch_incommand(command)
26231460Sminshall int command;
26331460Sminshall {
26431460Sminshall     int i;
26531460Sminshall 
26631493Sminshall     if ((i = api_exch_nextcommand()) == -1) {
26731493Sminshall 	return -1;
26831460Sminshall     }
26931460Sminshall     if (i != command) {
27031493Sminshall 	WHO_ARE_WE();
27131460Sminshall 	fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n",
27231460Sminshall 				command, i);
27331460Sminshall 	return -1;
27431460Sminshall     }
27531460Sminshall     return 0;
27631460Sminshall }
27731460Sminshall 
27831460Sminshall 
27931467Sminshall int
api_exch_outcommand(command)28031460Sminshall api_exch_outcommand(command)
28131460Sminshall int command;
28231460Sminshall {
28331493Sminshall     if (conversation != SEND) {
28431493Sminshall 	if (enter_send() == -1) {
28531460Sminshall 	    return -1;
28631460Sminshall 	}
28731460Sminshall     }
28831493Sminshall     exch_state.command_or_type = command;
28931493Sminshall     exch_state.opcode = EXCH_EXCH_COMMAND;
29031493Sminshall     if (send_state() == -1) {
29131493Sminshall 	return -1;
29231493Sminshall     } else {
29331493Sminshall 	return 0;
29431493Sminshall     }
29531460Sminshall }
29631460Sminshall 
29731460Sminshall 
29831467Sminshall int
api_exch_outtype(type,length,location)29931460Sminshall api_exch_outtype(type, length, location)
30031460Sminshall int
30131460Sminshall     type,
30231460Sminshall     length;
30331460Sminshall char
30431460Sminshall     *location;
30531460Sminshall {
30631801Sminshall     int netleng = length;
30731460Sminshall 
30831493Sminshall     if (conversation != SEND) {
30931493Sminshall 	if (enter_send() == -1) {
31031460Sminshall 	    return -1;
31131460Sminshall 	}
31231460Sminshall     }
31331493Sminshall     exch_state.opcode = EXCH_EXCH_TYPE;
31431493Sminshall     exch_state.command_or_type = type;
31531493Sminshall     exch_state.length = netleng;
31631493Sminshall     if (send_state() == -1) {
31731493Sminshall 	return -1;
31831493Sminshall     }
31931493Sminshall     if (length) {
32031493Sminshall 	if (OBUFROOM() > length) {
32131493Sminshall 	    OBUFADDBYTES(location, length);
32231493Sminshall 	} else {
32331493Sminshall 	    if (outflush() == -1) {
32431493Sminshall 		return -1;
32531493Sminshall 	    }
32631493Sminshall 	    if (write(sock, location, length) != length) {
32731493Sminshall 		WHO_ARE_WE();
32831493Sminshall 		perror("write");
32931493Sminshall 		return -1;
33031493Sminshall 	    }
33131460Sminshall 	}
33231460Sminshall     }
33331493Sminshall     return 0;
33431460Sminshall }
33531460Sminshall 
33631460Sminshall 
33731467Sminshall int
api_exch_intype(type,length,location)33831460Sminshall api_exch_intype(type, length, location)
33931460Sminshall int
34031460Sminshall     type,
34131460Sminshall     length;
34231460Sminshall char
34331460Sminshall     *location;
34431460Sminshall {
34535418Sminshall     int netleng = length;
34631460Sminshall 
34731493Sminshall     if (conversation != RECEIVE) {
34831493Sminshall 	if (enter_receive() == -1) {
34931460Sminshall 	    return -1;
35031460Sminshall 	}
35131460Sminshall     }
35231493Sminshall     if (receive_state() == -1) {
35331460Sminshall 	return -1;
35431460Sminshall     }
35531493Sminshall     if (exch_state.opcode != EXCH_EXCH_TYPE) {
35631493Sminshall 	WHO_ARE_WE();
35731493Sminshall 	fprintf(stderr,
35831493Sminshall 	    "Expected to receive a %s exchange, received a %s exchange.\n",
35931493Sminshall 	    exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode));
36031493Sminshall 	return -1;
36131493Sminshall     }
36231493Sminshall     if (exch_state.command_or_type != type) {
36331493Sminshall 	WHO_ARE_WE();
36431493Sminshall 	fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n",
36531493Sminshall 	    type, exch_state.command_or_type);
36631493Sminshall 	return -1;
36731493Sminshall     }
36831493Sminshall     if (exch_state.length != netleng) {
36935418Sminshall 	fprintf(stderr, "Type 0x%x - expected length %d, received length %u.\n",
37031801Sminshall 		type, length, exch_state.length);
37131460Sminshall 	return -1;
37231460Sminshall     }
37331499Sminshall     if (iget(location, length) == -1) {
37431499Sminshall 	return -1;
37531460Sminshall     }
37631460Sminshall     return 0;
37731460Sminshall }
37831467Sminshall 
37931467Sminshall int
api_exch_flush()38031493Sminshall api_exch_flush()
38131493Sminshall {
38231493Sminshall     return outflush();
38331493Sminshall }
38431493Sminshall 
38531493Sminshall int
api_exch_init(sock_number,ourname)38631474Sminshall api_exch_init(sock_number, ourname)
38731467Sminshall int sock_number;
38831474Sminshall char *ourname;
38931467Sminshall {
39035418Sminshall     extern char *strcpy();
39135418Sminshall 
39231467Sminshall     sock = sock_number;
39335418Sminshall     (void) strcpy(whoarewe, ourname);		/* For error messages */
39431467Sminshall 
39531493Sminshall     my_sequence = your_sequence = 0;
39631493Sminshall 
39731493Sminshall     conversation = CONTENTION;		/* We don't know which direction */
39831493Sminshall 
39931467Sminshall     IBUFRESET();
40031467Sminshall     OBUFRESET();
40131467Sminshall 
40231467Sminshall     return 0;
40331467Sminshall }
404