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