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