Annotation of 43BSDReno/usr.bin/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 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: }

unix.superglobalmegacorp.com

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