xref: /csrg-svn/usr.bin/tn3270/api/api_exch.c (revision 35418)
131890Sminshall /*
233820Sbostic  * Copyright (c) 1988 Regents of the University of California.
333820Sbostic  * All rights reserved.
431890Sminshall  *
533820Sbostic  * Redistribution and use in source and binary forms are permitted
6*35418Sminshall  * provided that the above copyright notice and this paragraph are
7*35418Sminshall  * duplicated in all such forms and that any documentation,
8*35418Sminshall  * advertising materials, and other materials related to such
9*35418Sminshall  * distribution and use acknowledge that the software was developed
10*35418Sminshall  * by the University of California, Berkeley.  The name of the
11*35418Sminshall  * University may not be used to endorse or promote products derived
12*35418Sminshall  * from this software without specific prior written permission.
13*35418Sminshall  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*35418Sminshall  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*35418Sminshall  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1631890Sminshall  */
1731890Sminshall 
1831890Sminshall #ifndef lint
19*35418Sminshall static char sccsid[] = "@(#)api_exch.c	3.3 (Berkeley) 08/28/88";
2033820Sbostic #endif /* not lint */
2131890Sminshall 
2231460Sminshall #include <stdio.h>
2331460Sminshall 
2431801Sminshall #include "../general/general.h"
2531801Sminshall 
2631460Sminshall #include "api_exch.h"
2731460Sminshall 
2831467Sminshall static int sock;		/* Socket number */
2931467Sminshall 
3031474Sminshall static char whoarewe[40] = "";
3131493Sminshall #define	WHO_ARE_WE()	fprintf(stderr, "(API %s) ", whoarewe);
3231474Sminshall 
3331493Sminshall static enum {CONTENTION, SEND, RECEIVE } conversation;
3431493Sminshall 
3531493Sminshall static struct exch_exch exch_state;
3631493Sminshall 
3731493Sminshall static unsigned int
3831493Sminshall     my_sequence,
3931493Sminshall     your_sequence;
4031493Sminshall 
4131499Sminshall static char ibuffer[4000], *ibuf_next, *ibuf_last;
4231460Sminshall #define	IBUFADDED(i)		ibuf_last += (i)
4331499Sminshall #define	IBUFAVAILABLE()		(ibuf_last-ibuf_next)
4431460Sminshall #define	IBUFFER()		ibuffer
4531499Sminshall #define	IBUFFREE()		(ibuffer+sizeof ibuffer-ibuf_last-1)
4631493Sminshall #define	IBUFGETBYTES(w,l)	{ memcpy(w, ibuf_next, l); ibuf_next += l; }
4731460Sminshall #define	IBUFRESET()		(ibuf_next = ibuf_last = ibuffer)
4831460Sminshall 
4931499Sminshall char obuffer[4000], *obuf_next;
5031460Sminshall #define	OBUFADDBYTES(w,l)	{ memcpy(obuf_next, w, l); obuf_next += l; }
5131460Sminshall #define	OBUFAVAILABLE()		(obuf_next - obuffer)
5231460Sminshall #define	OBUFFER()		obuffer
5331460Sminshall #define	OBUFRESET()		obuf_next = obuffer
5431460Sminshall #define	OBUFROOM()		(obuffer+sizeof obuffer-obuf_next)
5531460Sminshall 
5631460Sminshall 
5731460Sminshall static int
5831460Sminshall outflush()
5931460Sminshall {
6031460Sminshall     int length = OBUFAVAILABLE();
6131460Sminshall 
6231460Sminshall     if (length != 0) {
6331460Sminshall 	if (write(sock, OBUFFER(), length) != length) {
6431493Sminshall 	    WHO_ARE_WE();
6531474Sminshall 	    perror("write");
6631460Sminshall 	    return -1;
6731460Sminshall 	}
6831460Sminshall 	OBUFRESET();
6931460Sminshall     }
7031460Sminshall     return 0;				/* All OK */
7131460Sminshall }
7231460Sminshall 
7331460Sminshall 
7431460Sminshall static int
7531499Sminshall iget(location, length)
7631499Sminshall char	*location;
7731499Sminshall int	length;
7831460Sminshall {
7931499Sminshall     int count;
8031460Sminshall 
8131460Sminshall     if (OBUFAVAILABLE()) {
8231460Sminshall 	if (outflush() == -1) {
8331460Sminshall 	    return -1;
8431460Sminshall 	}
8531460Sminshall     }
8631499Sminshall     if ((count = IBUFAVAILABLE()) != 0) {
8731499Sminshall 	if (count > length) {
8831499Sminshall 	    count = length;
8931499Sminshall 	}
9031499Sminshall 	IBUFGETBYTES(location, count);
9131499Sminshall 	length -= count;
9231499Sminshall 	location += count;
9331460Sminshall     }
9431499Sminshall     while (length) {
9531499Sminshall 	if (ibuf_next == ibuf_last) {
9631499Sminshall 	    IBUFRESET();
9731499Sminshall 	}
9831499Sminshall 	if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) {
9931493Sminshall 	    WHO_ARE_WE();
10031474Sminshall 	    perror("read");
10131460Sminshall 	    return -1;
10231460Sminshall 	}
10331499Sminshall 	if (count == 0) {
10431474Sminshall 	    /* Reading past end-of-file */
10531493Sminshall 	    WHO_ARE_WE();
10631493Sminshall 	    fprintf(stderr, "End of file read\r\n");
10731474Sminshall 	    return -1;
10831474Sminshall 	}
10931499Sminshall 	IBUFADDED(count);
11031499Sminshall 	if (count > length) {
11131499Sminshall 	    count = length;
11231499Sminshall 	}
11331499Sminshall 	IBUFGETBYTES(location, count);
11431499Sminshall 	length -= count;
11531499Sminshall 	location += count;
11631460Sminshall     }
11731460Sminshall     return 0;
11831460Sminshall }
11931460Sminshall 
12031493Sminshall static char *
12131493Sminshall exch_to_ascii(exch)
12231493Sminshall int exch;			/* opcode to decode */
12331493Sminshall {
12431493Sminshall     switch (exch) {
12531493Sminshall     case EXCH_EXCH_COMMAND:
12631493Sminshall 	return "Command";
12731493Sminshall     case EXCH_EXCH_TYPE:
12831493Sminshall 	return "Type";
12931493Sminshall     case EXCH_EXCH_TURNAROUND:
13031493Sminshall 	return "Turnaround";
13131493Sminshall     case EXCH_EXCH_RTS:
13231493Sminshall 	return "Request to Send";
13331493Sminshall     default:
13431493Sminshall 	{
13531493Sminshall 	    static char unknown[40];
13631493Sminshall 
13731493Sminshall 	    sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff);
13831493Sminshall 	    return unknown;
13931493Sminshall 	}
14031493Sminshall     }
14131493Sminshall }
14231493Sminshall 
14331493Sminshall /*
14431493Sminshall  * Send the exch structure, updating the sequnce number field.
14531493Sminshall  */
14631493Sminshall 
14731493Sminshall static int
14831493Sminshall send_state()
14931493Sminshall {
15031493Sminshall     if (OBUFROOM() < sizeof exch_state) {
15131493Sminshall 	if (outflush() == -1) {
15231493Sminshall 	    return -1;
15331493Sminshall 	}
15431493Sminshall     }
15531498Sminshall     my_sequence = (my_sequence+1)&0xff;
15631498Sminshall     exch_state.my_sequence = my_sequence;
15731493Sminshall     exch_state.your_sequence = your_sequence;
15831493Sminshall     OBUFADDBYTES((char *)&exch_state, sizeof exch_state);
15931493Sminshall     return 0;
16031493Sminshall }
16131493Sminshall 
16231493Sminshall /*
16331493Sminshall  * Receive the exch structure from the other side, checking
16431493Sminshall  * sequence numbering.
16531493Sminshall  */
16631493Sminshall 
16731493Sminshall static int
16831493Sminshall receive_state()
16931493Sminshall {
17031499Sminshall     if (iget((char *)&exch_state, sizeof exch_state) == -1) {
17131499Sminshall 	return -1;
17231493Sminshall     }
17331493Sminshall     if (conversation != CONTENTION) {
17431493Sminshall 	if (exch_state.your_sequence != my_sequence) {
17531493Sminshall 	    WHO_ARE_WE();
17631493Sminshall 	    fprintf(stderr, "Send sequence number mismatch.\n");
17731493Sminshall 	    return -1;
17831493Sminshall 	}
17931498Sminshall 	if (exch_state.my_sequence != ((++your_sequence)&0xff)) {
18031493Sminshall 	    WHO_ARE_WE();
18131493Sminshall 	    fprintf(stderr, "Receive sequence number mismatch.\n");
18231493Sminshall 	    return -1;
18331493Sminshall 	}
18431493Sminshall     }
18531498Sminshall     your_sequence = exch_state.my_sequence;
18631493Sminshall     return 0;
18731493Sminshall }
18831493Sminshall 
18931493Sminshall static int
19031493Sminshall enter_receive()
19131493Sminshall {
19231493Sminshall     switch (conversation) {
19331493Sminshall     case CONTENTION:
19431493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
19531493Sminshall 	if (send_state() == -1) {
19631493Sminshall 	    return -1;
19731493Sminshall 	}
19831493Sminshall 	if (receive_state() == -1) {
19931493Sminshall 	    return -1;
20031493Sminshall 	}
20131493Sminshall 	if (exch_state.opcode != EXCH_EXCH_RTS) {
20231493Sminshall 	    WHO_ARE_WE();
20331493Sminshall 	    fprintf(stderr, "In CONTENTION state:  ");
20431493Sminshall 	    if (exch_state.opcode == EXCH_EXCH_TURNAROUND) {
20531493Sminshall 		fprintf(stderr,
20631493Sminshall 		    "Both sides tried to enter RECEIVE state.\n");
20731493Sminshall 	    } else {
20831493Sminshall 		fprintf(stderr,
20931493Sminshall 		    "Protocol error trying to enter RECEIVE state.\n");
21031493Sminshall 	    }
21131493Sminshall 	    return -1;
21231493Sminshall 	}
21331493Sminshall 	break;
21431493Sminshall     case SEND:
21531493Sminshall 	exch_state.opcode = EXCH_EXCH_TURNAROUND;
21631493Sminshall 	if (send_state() == -1) {
21731493Sminshall 	    return -1;
21831493Sminshall 	}
21931493Sminshall 	break;
22031493Sminshall     }
22131493Sminshall     conversation = RECEIVE;
22231493Sminshall     return 0;
22331493Sminshall }
22431493Sminshall 
22531493Sminshall static int
22631493Sminshall enter_send()
22731493Sminshall {
22831493Sminshall     switch (conversation) {
22931493Sminshall     case CONTENTION:
23031493Sminshall 	exch_state.opcode = EXCH_EXCH_RTS;
23131493Sminshall 	if (send_state() == -1) {
23231493Sminshall 	    return -1;
23331493Sminshall 	}
23431493Sminshall 	 /* fall through */
23531493Sminshall     case RECEIVE:
23631493Sminshall 	if (receive_state() == -1) {
23731493Sminshall 	    return -1;
23831493Sminshall 	}
23931493Sminshall 	if (exch_state.opcode != EXCH_EXCH_TURNAROUND) {
24031493Sminshall 	    WHO_ARE_WE();
24131493Sminshall 	    fprintf(stderr, "Conversation error - both sides in SEND state.\n");
24231493Sminshall 	    return -1;
24331493Sminshall 	}
24431493Sminshall     }
24531493Sminshall     conversation = SEND;
24631493Sminshall     return 0;
24731493Sminshall }
24831493Sminshall 
24931467Sminshall int
25031493Sminshall api_exch_nextcommand()
25131467Sminshall {
25231493Sminshall     if (conversation != RECEIVE) {
25331493Sminshall 	if (enter_receive() == -1) {
25431467Sminshall 	    return -1;
25531467Sminshall 	}
25631467Sminshall     }
25731493Sminshall     if (receive_state() == -1) {
25831493Sminshall 	return -1;
25931493Sminshall     }
26031493Sminshall     if (exch_state.opcode != EXCH_EXCH_COMMAND) {
26131493Sminshall 	WHO_ARE_WE();
26231493Sminshall 	fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n",
26331493Sminshall 	    exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode));
26431493Sminshall 	return -1;
26531493Sminshall     }
26631493Sminshall     return exch_state.command_or_type;
26731467Sminshall }
26831467Sminshall 
26931467Sminshall 
27031467Sminshall int
27131460Sminshall api_exch_incommand(command)
27231460Sminshall int command;
27331460Sminshall {
27431460Sminshall     int i;
27531460Sminshall 
27631493Sminshall     if ((i = api_exch_nextcommand()) == -1) {
27731493Sminshall 	return -1;
27831460Sminshall     }
27931460Sminshall     if (i != command) {
28031493Sminshall 	WHO_ARE_WE();
28131460Sminshall 	fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n",
28231460Sminshall 				command, i);
28331460Sminshall 	return -1;
28431460Sminshall     }
28531460Sminshall     return 0;
28631460Sminshall }
28731460Sminshall 
28831460Sminshall 
28931467Sminshall int
29031460Sminshall api_exch_outcommand(command)
29131460Sminshall int command;
29231460Sminshall {
29331493Sminshall     if (conversation != SEND) {
29431493Sminshall 	if (enter_send() == -1) {
29531460Sminshall 	    return -1;
29631460Sminshall 	}
29731460Sminshall     }
29831493Sminshall     exch_state.command_or_type = command;
29931493Sminshall     exch_state.opcode = EXCH_EXCH_COMMAND;
30031493Sminshall     if (send_state() == -1) {
30131493Sminshall 	return -1;
30231493Sminshall     } else {
30331493Sminshall 	return 0;
30431493Sminshall     }
30531460Sminshall }
30631460Sminshall 
30731460Sminshall 
30831467Sminshall int
30931460Sminshall api_exch_outtype(type, length, location)
31031460Sminshall int
31131460Sminshall     type,
31231460Sminshall     length;
31331460Sminshall char
31431460Sminshall     *location;
31531460Sminshall {
31631801Sminshall     int netleng = length;
31731460Sminshall 
31831493Sminshall     if (conversation != SEND) {
31931493Sminshall 	if (enter_send() == -1) {
32031460Sminshall 	    return -1;
32131460Sminshall 	}
32231460Sminshall     }
32331493Sminshall     exch_state.opcode = EXCH_EXCH_TYPE;
32431493Sminshall     exch_state.command_or_type = type;
32531493Sminshall     exch_state.length = netleng;
32631493Sminshall     if (send_state() == -1) {
32731493Sminshall 	return -1;
32831493Sminshall     }
32931493Sminshall     if (length) {
33031493Sminshall 	if (OBUFROOM() > length) {
33131493Sminshall 	    OBUFADDBYTES(location, length);
33231493Sminshall 	} else {
33331493Sminshall 	    if (outflush() == -1) {
33431493Sminshall 		return -1;
33531493Sminshall 	    }
33631493Sminshall 	    if (write(sock, location, length) != length) {
33731493Sminshall 		WHO_ARE_WE();
33831493Sminshall 		perror("write");
33931493Sminshall 		return -1;
34031493Sminshall 	    }
34131460Sminshall 	}
34231460Sminshall     }
34331493Sminshall     return 0;
34431460Sminshall }
34531460Sminshall 
34631460Sminshall 
34731467Sminshall int
34831460Sminshall api_exch_intype(type, length, location)
34931460Sminshall int
35031460Sminshall     type,
35131460Sminshall     length;
35231460Sminshall char
35331460Sminshall     *location;
35431460Sminshall {
355*35418Sminshall     int netleng = length;
35631460Sminshall 
35731493Sminshall     if (conversation != RECEIVE) {
35831493Sminshall 	if (enter_receive() == -1) {
35931460Sminshall 	    return -1;
36031460Sminshall 	}
36131460Sminshall     }
36231493Sminshall     if (receive_state() == -1) {
36331460Sminshall 	return -1;
36431460Sminshall     }
36531493Sminshall     if (exch_state.opcode != EXCH_EXCH_TYPE) {
36631493Sminshall 	WHO_ARE_WE();
36731493Sminshall 	fprintf(stderr,
36831493Sminshall 	    "Expected to receive a %s exchange, received a %s exchange.\n",
36931493Sminshall 	    exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode));
37031493Sminshall 	return -1;
37131493Sminshall     }
37231493Sminshall     if (exch_state.command_or_type != type) {
37331493Sminshall 	WHO_ARE_WE();
37431493Sminshall 	fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n",
37531493Sminshall 	    type, exch_state.command_or_type);
37631493Sminshall 	return -1;
37731493Sminshall     }
37831493Sminshall     if (exch_state.length != netleng) {
379*35418Sminshall 	fprintf(stderr, "Type 0x%x - expected length %d, received length %u.\n",
38031801Sminshall 		type, length, exch_state.length);
38131460Sminshall 	return -1;
38231460Sminshall     }
38331499Sminshall     if (iget(location, length) == -1) {
38431499Sminshall 	return -1;
38531460Sminshall     }
38631460Sminshall     return 0;
38731460Sminshall }
38831467Sminshall 
38931467Sminshall int
39031493Sminshall api_exch_flush()
39131493Sminshall {
39231493Sminshall     return outflush();
39331493Sminshall }
39431493Sminshall 
39531493Sminshall int
39631474Sminshall api_exch_init(sock_number, ourname)
39731467Sminshall int sock_number;
39831474Sminshall char *ourname;
39931467Sminshall {
400*35418Sminshall     extern char *strcpy();
401*35418Sminshall 
40231467Sminshall     sock = sock_number;
403*35418Sminshall     (void) strcpy(whoarewe, ourname);		/* For error messages */
40431467Sminshall 
40531493Sminshall     my_sequence = your_sequence = 0;
40631493Sminshall 
40731493Sminshall     conversation = CONTENTION;		/* We don't know which direction */
40831493Sminshall 
40931467Sminshall     IBUFRESET();
41031467Sminshall     OBUFRESET();
41131467Sminshall 
41231467Sminshall     return 0;
41331467Sminshall }
414