Annotation of 43BSDTahoe/ucb/tn3270/api/api_exch.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.