Install sccs headers and copyright notices.
[unix-history] / usr / src / usr.bin / tn3270 / api / api_exch.c
CommitLineData
992de934
GM
1/*
2 * Copyright (c) 1984-1987 by the Regents of the
3 * University of California and by Gregory Glenn Minshall.
4 *
5 * Permission to use, copy, modify, and distribute these
6 * programs and their documentation for any purpose and
7 * without fee is hereby granted, provided that this
8 * copyright and permission appear on all copies and
9 * supporting documentation, the name of the Regents of
10 * the University of California not be used in advertising
11 * or publicity pertaining to distribution of the programs
12 * without specific prior permission, and notice be given in
13 * supporting documentation that copying and distribution is
14 * by permission of the Regents of the University of California
15 * and by Gregory Glenn Minshall. Neither the Regents of the
16 * University of California nor Gregory Glenn Minshall make
17 * representations about the suitability of this software
18 * for any purpose. It is provided "as is" without
19 * express or implied warranty.
20 */
21
22#ifndef lint
23static char sccsid[] = "@(#)api_exch.c 1.8 (Berkeley) %G%";
24#endif /* not lint */
25
ba212048
GM
26#include <stdio.h>
27
1117b0bd
GM
28#include "../general/general.h"
29
ba212048
GM
30#include "api_exch.h"
31
62946391
GM
32static int sock; /* Socket number */
33
224a681b 34static char whoarewe[40] = "";
d024bcc4
GM
35#define WHO_ARE_WE() fprintf(stderr, "(API %s) ", whoarewe);
36
37static enum {CONTENTION, SEND, RECEIVE } conversation;
38
39static struct exch_exch exch_state;
40
41static unsigned int
42 my_sequence,
43 your_sequence;
224a681b 44
8d951982 45static char ibuffer[4000], *ibuf_next, *ibuf_last;
ba212048 46#define IBUFADDED(i) ibuf_last += (i)
8d951982 47#define IBUFAVAILABLE() (ibuf_last-ibuf_next)
ba212048 48#define IBUFFER() ibuffer
8d951982 49#define IBUFFREE() (ibuffer+sizeof ibuffer-ibuf_last-1)
d024bcc4 50#define IBUFGETBYTES(w,l) { memcpy(w, ibuf_next, l); ibuf_next += l; }
ba212048
GM
51#define IBUFRESET() (ibuf_next = ibuf_last = ibuffer)
52
8d951982 53char obuffer[4000], *obuf_next;
ba212048 54#define OBUFADDBYTES(w,l) { memcpy(obuf_next, w, l); obuf_next += l; }
ba212048
GM
55#define OBUFAVAILABLE() (obuf_next - obuffer)
56#define OBUFFER() obuffer
57#define OBUFRESET() obuf_next = obuffer
58#define OBUFROOM() (obuffer+sizeof obuffer-obuf_next)
59
60
61static int
62outflush()
63{
64 int length = OBUFAVAILABLE();
65
66 if (length != 0) {
67 if (write(sock, OBUFFER(), length) != length) {
d024bcc4 68 WHO_ARE_WE();
224a681b 69 perror("write");
ba212048
GM
70 return -1;
71 }
72 OBUFRESET();
73 }
74 return 0; /* All OK */
75}
76
77
78static int
8d951982
GM
79iget(location, length)
80char *location;
81int length;
ba212048
GM
82{
83 int i;
8d951982 84 int count;
ba212048
GM
85
86 if (OBUFAVAILABLE()) {
87 if (outflush() == -1) {
88 return -1;
89 }
90 }
8d951982
GM
91 if ((count = IBUFAVAILABLE()) != 0) {
92 if (count > length) {
93 count = length;
94 }
95 IBUFGETBYTES(location, count);
96 length -= count;
97 location += count;
d024bcc4 98 }
8d951982
GM
99 while (length) {
100 if (ibuf_next == ibuf_last) {
101 IBUFRESET();
102 }
103 if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) {
d024bcc4 104 WHO_ARE_WE();
224a681b
GM
105 perror("read");
106 return -1;
107 }
8d951982 108 if (count == 0) {
224a681b 109 /* Reading past end-of-file */
d024bcc4
GM
110 WHO_ARE_WE();
111 fprintf(stderr, "End of file read\r\n");
ba212048
GM
112 return -1;
113 }
8d951982
GM
114 IBUFADDED(count);
115 if (count > length) {
116 count = length;
117 }
118 IBUFGETBYTES(location, count);
119 length -= count;
120 location += count;
ba212048
GM
121 }
122 return 0;
123}
124
d024bcc4
GM
125static char *
126exch_to_ascii(exch)
127int exch; /* opcode to decode */
128{
129 switch (exch) {
130 case EXCH_EXCH_COMMAND:
131 return "Command";
132 case EXCH_EXCH_TYPE:
133 return "Type";
134 case EXCH_EXCH_TURNAROUND:
135 return "Turnaround";
136 case EXCH_EXCH_RTS:
137 return "Request to Send";
138 default:
139 {
140 static char unknown[40];
141
142 sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff);
143 return unknown;
144 }
145 }
146}
147
148/*
149 * Send the exch structure, updating the sequnce number field.
150 */
151
152static int
153send_state()
154{
155 if (OBUFROOM() < sizeof exch_state) {
156 if (outflush() == -1) {
157 return -1;
158 }
159 }
e1e082cf
GM
160 my_sequence = (my_sequence+1)&0xff;
161 exch_state.my_sequence = my_sequence;
d024bcc4
GM
162 exch_state.your_sequence = your_sequence;
163 OBUFADDBYTES((char *)&exch_state, sizeof exch_state);
164 return 0;
165}
166
167/*
168 * Receive the exch structure from the other side, checking
169 * sequence numbering.
170 */
171
172static int
173receive_state()
174{
8d951982
GM
175 if (iget((char *)&exch_state, sizeof exch_state) == -1) {
176 return -1;
d024bcc4 177 }
d024bcc4
GM
178 if (conversation != CONTENTION) {
179 if (exch_state.your_sequence != my_sequence) {
180 WHO_ARE_WE();
181 fprintf(stderr, "Send sequence number mismatch.\n");
182 return -1;
183 }
e1e082cf 184 if (exch_state.my_sequence != ((++your_sequence)&0xff)) {
d024bcc4
GM
185 WHO_ARE_WE();
186 fprintf(stderr, "Receive sequence number mismatch.\n");
187 return -1;
188 }
d024bcc4 189 }
e1e082cf 190 your_sequence = exch_state.my_sequence;
d024bcc4
GM
191 return 0;
192}
193
194static int
195enter_receive()
196{
197 switch (conversation) {
198 case CONTENTION:
199 exch_state.opcode = EXCH_EXCH_TURNAROUND;
200 if (send_state() == -1) {
201 return -1;
202 }
203 if (receive_state() == -1) {
204 return -1;
205 }
206 if (exch_state.opcode != EXCH_EXCH_RTS) {
207 WHO_ARE_WE();
208 fprintf(stderr, "In CONTENTION state: ");
209 if (exch_state.opcode == EXCH_EXCH_TURNAROUND) {
210 fprintf(stderr,
211 "Both sides tried to enter RECEIVE state.\n");
212 } else {
213 fprintf(stderr,
214 "Protocol error trying to enter RECEIVE state.\n");
215 }
216 return -1;
217 }
218 break;
219 case SEND:
220 exch_state.opcode = EXCH_EXCH_TURNAROUND;
221 if (send_state() == -1) {
222 return -1;
223 }
224 break;
225 }
226 conversation = RECEIVE;
227 return 0;
228}
229
230static int
231enter_send()
232{
233 switch (conversation) {
234 case CONTENTION:
235 exch_state.opcode = EXCH_EXCH_RTS;
236 if (send_state() == -1) {
237 return -1;
238 }
239 /* fall through */
240 case RECEIVE:
241 if (receive_state() == -1) {
242 return -1;
243 }
244 if (exch_state.opcode != EXCH_EXCH_TURNAROUND) {
245 WHO_ARE_WE();
246 fprintf(stderr, "Conversation error - both sides in SEND state.\n");
247 return -1;
248 }
249 }
250 conversation = SEND;
251 return 0;
252}
253
62946391 254int
d024bcc4 255api_exch_nextcommand()
62946391 256{
d024bcc4
GM
257 if (conversation != RECEIVE) {
258 if (enter_receive() == -1) {
62946391
GM
259 return -1;
260 }
261 }
d024bcc4
GM
262 if (receive_state() == -1) {
263 return -1;
264 }
265 if (exch_state.opcode != EXCH_EXCH_COMMAND) {
266 WHO_ARE_WE();
267 fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n",
268 exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode));
269 return -1;
270 }
271 return exch_state.command_or_type;
62946391
GM
272}
273
274
275int
ba212048
GM
276api_exch_incommand(command)
277int command;
278{
279 int i;
280
d024bcc4
GM
281 if ((i = api_exch_nextcommand()) == -1) {
282 return -1;
ba212048 283 }
ba212048 284 if (i != command) {
d024bcc4 285 WHO_ARE_WE();
ba212048
GM
286 fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n",
287 command, i);
288 return -1;
289 }
290 return 0;
291}
292
293
62946391 294int
ba212048
GM
295api_exch_outcommand(command)
296int command;
297{
d024bcc4
GM
298 if (conversation != SEND) {
299 if (enter_send() == -1) {
ba212048
GM
300 return -1;
301 }
302 }
d024bcc4
GM
303 exch_state.command_or_type = command;
304 exch_state.opcode = EXCH_EXCH_COMMAND;
305 if (send_state() == -1) {
306 return -1;
307 } else {
308 return 0;
309 }
ba212048
GM
310}
311
312
62946391 313int
ba212048
GM
314api_exch_outtype(type, length, location)
315int
316 type,
317 length;
318char
319 *location;
320{
1117b0bd 321 int netleng = length;
ba212048 322
d024bcc4
GM
323 if (conversation != SEND) {
324 if (enter_send() == -1) {
ba212048
GM
325 return -1;
326 }
327 }
d024bcc4
GM
328 exch_state.opcode = EXCH_EXCH_TYPE;
329 exch_state.command_or_type = type;
330 exch_state.length = netleng;
331 if (send_state() == -1) {
332 return -1;
333 }
334 if (length) {
335 if (OBUFROOM() > length) {
336 OBUFADDBYTES(location, length);
337 } else {
338 if (outflush() == -1) {
339 return -1;
340 }
341 if (write(sock, location, length) != length) {
342 WHO_ARE_WE();
343 perror("write");
344 return -1;
345 }
ba212048
GM
346 }
347 }
d024bcc4 348 return 0;
ba212048
GM
349}
350
351
62946391 352int
ba212048
GM
353api_exch_intype(type, length, location)
354int
355 type,
356 length;
357char
358 *location;
359{
1117b0bd 360 int i, netleng = length;
ba212048 361
d024bcc4
GM
362 if (conversation != RECEIVE) {
363 if (enter_receive() == -1) {
ba212048
GM
364 return -1;
365 }
366 }
d024bcc4
GM
367 if (receive_state() == -1) {
368 return -1;
369 }
370 if (exch_state.opcode != EXCH_EXCH_TYPE) {
371 WHO_ARE_WE();
372 fprintf(stderr,
373 "Expected to receive a %s exchange, received a %s exchange.\n",
374 exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode));
ba212048
GM
375 return -1;
376 }
d024bcc4
GM
377 if (exch_state.command_or_type != type) {
378 WHO_ARE_WE();
379 fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n",
380 type, exch_state.command_or_type);
381 return -1;
382 }
383 if (exch_state.length != netleng) {
ba212048 384 fprintf(stderr, "Type 0x%x - expected length %d, received length %d.\n",
1117b0bd 385 type, length, exch_state.length);
ba212048
GM
386 return -1;
387 }
8d951982
GM
388 if (iget(location, length) == -1) {
389 return -1;
ba212048
GM
390 }
391 return 0;
392}
62946391 393
d024bcc4
GM
394int
395api_exch_flush()
396{
397 return outflush();
398}
399
62946391 400int
224a681b 401api_exch_init(sock_number, ourname)
62946391 402int sock_number;
224a681b 403char *ourname;
62946391
GM
404{
405 sock = sock_number;
224a681b 406 strcpy(whoarewe, ourname); /* For error messages */
62946391 407
d024bcc4
GM
408 my_sequence = your_sequence = 0;
409
410 conversation = CONTENTION; /* We don't know which direction */
411
62946391
GM
412 IBUFRESET();
413 OBUFRESET();
414
415 return 0;
416}