home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tn3270 / api / api_exch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-26  |  9.3 KB  |  430 lines

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