Annotation of coherent/g/usr/lib/uucp/tay104/protg.c, revision 1.1

1.1     ! root        1: /* protg.c
        !             2:    The 'g' protocol.
        !             3: 
        !             4:    Copyright (C) 1991, 1992 Ian Lance Taylor
        !             5: 
        !             6:    This file is part of the Taylor UUCP package.
        !             7: 
        !             8:    This program is free software; you can redistribute it and/or
        !             9:    modify it under the terms of the GNU General Public License as
        !            10:    published by the Free Software Foundation; either version 2 of the
        !            11:    License, or (at your option) any later version.
        !            12: 
        !            13:    This program is distributed in the hope that it will be useful, but
        !            14:    WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            16:    General Public License for more details.
        !            17: 
        !            18:    You should have received a copy of the GNU General Public License
        !            19:    along with this program; if not, write to the Free Software
        !            20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            21: 
        !            22:    The author of the program may be contacted at [email protected] or
        !            23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
        !            24:    */
        !            25: 
        !            26: #include "uucp.h"
        !            27: 
        !            28: #if USE_RCS_ID
        !            29: const char protg_rcsid[] = "$Id: protg.c,v 1.1 93/07/30 07:53:21 bin Exp Locker: bin $";
        !            30: #endif
        !            31: 
        !            32: #include <ctype.h>
        !            33: #include <errno.h>
        !            34: 
        !            35: #include "uudefs.h"
        !            36: #include "uuconf.h"
        !            37: #include "conn.h"
        !            38: #include "trans.h"
        !            39: #include "system.h"
        !            40: #include "prot.h"
        !            41: 
        !            42: /* Each 'g' protocol packet begins with six bytes.  They are:
        !            43: 
        !            44:    <DLE><k><c0><c1><C><x>
        !            45: 
        !            46:    <DLE> is the ASCII DLE character (^P or '\020').
        !            47:    if 1 <= <k> <= 8, the packet is followed by 2 ** (k + 4) bytes of data;
        !            48:    if <k> == 9, these six bytes are a complete control packet;
        !            49:    other value of <k> are illegal.
        !            50:    <c0> is the low byte of a checksum.
        !            51:    <c1> is the high byte of a checksum.
        !            52:    <C> is a control byte (see below).
        !            53:    <x> is <k> ^ <c0> ^ <c1> ^ <C>.
        !            54: 
        !            55:    The control byte <C> is divided into three bitfields:
        !            56: 
        !            57:    t t x x x y y y
        !            58: 
        !            59:    The two bit field tt is the packet type.
        !            60:    The three bit field xxx is the control type for a control packet, or
        !            61:    the sequence number for a data packet.
        !            62:    The three bit field yyy is a value for a control packet, or the
        !            63:    sequence number of the last packet received for a data packet.
        !            64: 
        !            65:    For all successfully recieved packets, the control byte is stored
        !            66:    into iGpacket_control.  */
        !            67: 
        !            68: /* Names for the bytes in the frame header.  */
        !            69: #define IFRAME_DLE (0)
        !            70: #define IFRAME_K (1)
        !            71: #define IFRAME_CHECKLOW (2)
        !            72: #define IFRAME_CHECKHIGH (3)
        !            73: #define IFRAME_CONTROL (4)
        !            74: #define IFRAME_XOR (5)
        !            75: 
        !            76: /* Length of the frame header.  */
        !            77: #define CFRAMELEN (6)
        !            78: 
        !            79: /* Macros to break apart the control bytes.  */
        !            80: #define CONTROL_TT(b) ((int)(((b) >> 6) & 03))
        !            81: #define CONTROL_XXX(b) ((int)(((b) >> 3) & 07))
        !            82: #define CONTROL_YYY(b) ((int)((b) & 07))
        !            83: 
        !            84: /* DLE value.  */
        !            85: #define DLE ('\020')
        !            86: 
        !            87: /* Get the length of a packet given a pointer to the header.  */
        !            88: #define CPACKLEN(z) ((size_t) (1 << ((z)[IFRAME_K] + 4)))
        !            89: 
        !            90: /* <k> field value for a control message.  */
        !            91: #define KCONTROL (9)
        !            92: 
        !            93: /* Get the next sequence number given a sequence number.  */
        !            94: #define INEXTSEQ(i) ((i + 1) & 07)
        !            95: 
        !            96: /* Compute i1 - i2 modulo 8.  */
        !            97: #define CSEQDIFF(i1, i2) (((i1) + 8 - (i2)) & 07)
        !            98: 
        !            99: /* Packet types.  These are from the tt field.
        !           100:    CONTROL -- control packet
        !           101:    ALTCHAN -- alternate channel; not used by UUCP
        !           102:    DATA -- full data segment
        !           103:    SHORTDATA -- less than full data segment (all the bytes specified by
        !           104:    the packet length <k> are always transferred).  Let <u> be the number
        !           105:    of bytes in the data segment not to be used.  If <u> <= 0x7f, the first
        !           106:    byte of the data segment is <u> and the data follows.  If <u> > 0x7f,
        !           107:    the first byte of the data segment is 0x80 | (<u> & 0x7f), the second
        !           108:    byte of the data segment is <u> >> 7, and the data follows.  The
        !           109:    maximum possible data segment size is 2**12, so this handles all
        !           110:    possible cases.  */
        !           111: #define CONTROL (0)
        !           112: #define ALTCHAN (1)
        !           113: #define DATA (2)
        !           114: #define SHORTDATA (3)
        !           115: 
        !           116: /* Control types.  These are from the xxx field if the type (tt field)
        !           117:    is CONTROL.
        !           118: 
        !           119:    CLOSE -- close the connection
        !           120:    RJ -- reject; packet yyy last to be received correctly
        !           121:    SRJ -- selective reject; reject only packet yyy (not used by UUCP)
        !           122:    RR -- receiver ready; packet yyy received correctly
        !           123:    INITC -- third step of initialization; yyy holds window size
        !           124:    INITB -- second step of initialization; yyy holds maximum <k> value - 1
        !           125:    INITA -- first step of initialization; yyy holds window size.
        !           126: 
        !           127:    The yyy value for RR is the same as the yyy value for an ordinary
        !           128:    data packet.  */
        !           129: #define CLOSE (1)
        !           130: #define RJ (2)
        !           131: #define SRJ (3)
        !           132: #define RR (4)
        !           133: #define INITC (5)
        !           134: #define INITB (6)
        !           135: #define INITA (7)
        !           136: 
        !           137: /* Maximum amount of data in a single packet.  This is set by the <k>
        !           138:    field in the header; the amount of data in a packet is
        !           139:    2 ** (<k> + 4).  <k> ranges from 1 to 8.  */
        !           140:     
        !           141: #define CMAXDATAINDEX (8)
        !           142: 
        !           143: #define CMAXDATA (1 << (CMAXDATAINDEX + 4))
        !           144: 
        !           145: /* Maximum window size.  */
        !           146: #define CMAXWINDOW (7)
        !           147: 
        !           148: /* Defaults for the protocol parameters.  These may all be changed by
        !           149:    using the ``protocol-parameter g'' command, so there is no
        !           150:    particular reason to change the values given here.  */
        !           151: 
        !           152: /* The desired window size.  This is what we tell the other system to
        !           153:    use.  It must be between 1 and 7, and there's no reason to use less
        !           154:    than 7.  Protocol parameter ``window''.  */
        !           155: #define IWINDOW (7)
        !           156: 
        !           157: /* The desired packet size.  Many implementations only support 64 byte
        !           158:    packets.  Protocol parameter ``packet-size''.  */
        !           159: #define IPACKSIZE (64)
        !           160: 
        !           161: /* The number of times to retry the exchange of INIT packets when
        !           162:    starting the protocol.  Protocol parameter ``startup-retries''.  */
        !           163: #define CSTARTUP_RETRIES (8)
        !           164: 
        !           165: /* The timeout to use when waiting for an INIT packet when starting up
        !           166:    the protocol.  Protocol parameter ``init-timeout''.  */
        !           167: #define CEXCHANGE_INIT_TIMEOUT (10)
        !           168: 
        !           169: /* The number of times to retry sending and waiting for a single INIT
        !           170:    packet when starting the protocol.  This controls a single INIT
        !           171:    packet, while CSTARTUP_RETRIES controls how many times to try the
        !           172:    entire INIT sequence.  Protocol parameter ``init-retries''.  */
        !           173: #define CEXCHANGE_INIT_RETRIES (4)
        !           174: 
        !           175: /* The timeout to use when waiting for a packet.  Protocol parameter
        !           176:    ``timeout''.  */
        !           177: #define CTIMEOUT (10)
        !           178: 
        !           179: /* The number of times to retry waiting for a packet.  Each time the
        !           180:    timeout fails we send a copy of our last data packet or a reject
        !           181:    message for the packet we expect from the other side, depending on
        !           182:    whether we are waiting for an acknowledgement or a data packet.
        !           183:    This is the number of times we try doing that and then waiting
        !           184:    again.  Protocol parameter ``retries''.   */
        !           185: #define CRETRIES (6)
        !           186: 
        !           187: /* If we see more than this much unrecognized data, we drop the
        !           188:    connection.  This must be larger than a single packet size, which
        !           189:    means it must be larger than 4096 (the largest possible packet
        !           190:    size).  Protocol parameter ``garbage''.  */
        !           191: #define CGARBAGE (10000)
        !           192: 
        !           193: /* If we see more than this many protocol errors, we drop the
        !           194:    connection.  Protocol parameter ``errors''.  */
        !           195: #define CERRORS (100)
        !           196: 
        !           197: /* Default decay rate.  Each time we send or receive this many packets
        !           198:    succesfully, we decrement the error level by one (protocol
        !           199:    parameter ``error-decay'').  */
        !           200: #define CERROR_DECAY (10)
        !           201: 
        !           202: /* If this value is non-zero, it will be used as the remote window
        !           203:    size regardless of what the other side requested.  This can be
        !           204:    useful for dealing with some particularly flawed packages.  This
        !           205:    default value should always be 0, and protocol parameter
        !           206:    ``remote-window'' should be used for the affected systems.  */
        !           207: #define IREMOTE_WINDOW (0)
        !           208: 
        !           209: /* If this value is non-zero, it will be used as the packet size to
        !           210:    send to the remote system regardless of what it requested.  It's
        !           211:    difficult to imagine any circumstances where you would want to set
        !           212:    this.  Protocol parameter ``remote-packet-size''.  */
        !           213: #define IREMOTE_PACKSIZE (0)
        !           214: 
        !           215: /* Local variables.  */
        !           216: 
        !           217: /* Next sequence number to send.  */
        !           218: static int iGsendseq;
        !           219: 
        !           220: /* Last sequence number that has been acked.  */
        !           221: static int iGremote_ack;
        !           222: 
        !           223: /* Last sequence number to be retransmitted.  */
        !           224: static int iGretransmit_seq;
        !           225: 
        !           226: /* Last sequence number we have received.  */
        !           227: static int iGrecseq;
        !           228: 
        !           229: /* Last sequence number we have acked.  */
        !           230: static int iGlocal_ack;
        !           231: 
        !           232: /* Window size to request (protocol parameter ``window'').  */
        !           233: static int iGrequest_winsize = IWINDOW;
        !           234: 
        !           235: /* Packet size to request (protocol parameter ``packet-size'').  */
        !           236: static int iGrequest_packsize = IPACKSIZE;
        !           237: 
        !           238: /* Remote window size (set during handshake).  */
        !           239: static int iGremote_winsize;
        !           240: 
        !           241: /* Forced remote window size (protocol parameter ``remote-window'').  */
        !           242: static int iGforced_remote_winsize = IREMOTE_WINDOW;
        !           243: 
        !           244: /* Remote segment size (set during handshake).  This is one less than
        !           245:    the value in a packet header.  */
        !           246: static int iGremote_segsize;
        !           247: 
        !           248: /* Remote packet size (set based on iGremote_segsize).  */
        !           249: static size_t iGremote_packsize;
        !           250: 
        !           251: /* Forced remote packet size (protocol parameter
        !           252:    ``remote-packet-size'').  */
        !           253: static int iGforced_remote_packsize = IREMOTE_PACKSIZE;
        !           254: 
        !           255: /* Recieved control byte.  */
        !           256: static int iGpacket_control;
        !           257: 
        !           258: /* Number of times to retry the initial handshake.  Protocol parameter
        !           259:    ``startup-retries''.  */
        !           260: static int cGstartup_retries = CSTARTUP_RETRIES;
        !           261: 
        !           262: /* Number of times to retry sending an initial control packet.
        !           263:    Protocol parameter ``init-retries''.  */
        !           264: static int cGexchange_init_retries = CEXCHANGE_INIT_RETRIES;
        !           265: 
        !           266: /* Timeout (seconds) for receiving an initial control packet.
        !           267:    Protocol parameter ``init-timeout''.  */
        !           268: static int cGexchange_init_timeout = CEXCHANGE_INIT_TIMEOUT;
        !           269: 
        !           270: /* Timeout (seconds) for receiving a data packet.  Protocol parameter
        !           271:    ``timeout''.  */
        !           272: static int cGtimeout = CTIMEOUT;
        !           273: 
        !           274: /* Maximum number of timeouts when receiving a data packet or
        !           275:    acknowledgement.  Protocol parameter ``retries''.  */
        !           276: static int cGretries = CRETRIES;
        !           277: 
        !           278: /* Amount of garbage data we are prepared to see before giving up.
        !           279:    Protocol parameter ``garbage''.  */
        !           280: static int cGgarbage_data = CGARBAGE;
        !           281: 
        !           282: /* Maximum number of errors we are prepared to see before giving up.
        !           283:    Protocol parameter ``errors''.  */
        !           284: static int cGmax_errors = CERRORS;
        !           285: 
        !           286: /* Each time we receive this many packets succesfully, we decrement
        !           287:    the error level by one (protocol parameter ``error-decay'').  */
        !           288: static int cGerror_decay = CERROR_DECAY;
        !           289: 
        !           290: /* Whether to use shorter packets when possible.  Protocol parameter
        !           291:    ``short-packets''.  */
        !           292: static boolean fGshort_packets = TRUE;
        !           293: 
        !           294: /* Protocol parameter commands.  */
        !           295: struct uuconf_cmdtab asGproto_params[] =
        !           296: {
        !           297:   { "window", UUCONF_CMDTABTYPE_INT, (pointer) &iGrequest_winsize, NULL },
        !           298:   { "packet-size", UUCONF_CMDTABTYPE_INT, (pointer) &iGrequest_packsize,
        !           299:       NULL },
        !           300:   { "startup-retries", UUCONF_CMDTABTYPE_INT, (pointer) &cGstartup_retries,
        !           301:       NULL },
        !           302:   { "init-timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cGexchange_init_timeout,
        !           303:       NULL },
        !           304:   { "init-retries", UUCONF_CMDTABTYPE_INT, (pointer) &cGexchange_init_retries,
        !           305:       NULL },
        !           306:   { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cGtimeout, NULL },
        !           307:   { "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cGretries, NULL },
        !           308:   { "garbage", UUCONF_CMDTABTYPE_INT, (pointer) &cGgarbage_data, NULL },
        !           309:   { "errors", UUCONF_CMDTABTYPE_INT, (pointer) &cGmax_errors, NULL },
        !           310:   { "error-decay", UUCONF_CMDTABTYPE_INT, (pointer) &cGerror_decay, NULL },
        !           311:   { "remote-window", UUCONF_CMDTABTYPE_INT,
        !           312:       (pointer) &iGforced_remote_winsize, NULL },
        !           313:   { "remote-packet-size", UUCONF_CMDTABTYPE_INT,
        !           314:       (pointer) &iGforced_remote_packsize, NULL },
        !           315:   { "short-packets", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fGshort_packets,
        !           316:       NULL },
        !           317:   { NULL, 0, NULL, NULL }
        !           318: };
        !           319: 
        !           320: /* Statistics.  */
        !           321: 
        !           322: /* Number of packets we have sent.  */
        !           323: static long cGsent_packets;
        !           324: 
        !           325: /* Number of packets we have resent (these are not included in
        !           326:    cGsent_packets).  */
        !           327: static long cGresent_packets;
        !           328: 
        !           329: /* Number of packets we have delayed sending (these should not be
        !           330:    counted in cGresent_packets).  */
        !           331: static long cGdelayed_packets;
        !           332: 
        !           333: /* Number of packets we have received.  */
        !           334: static long cGrec_packets;
        !           335: 
        !           336: /* Number of packets rejected because the header was bad.  */
        !           337: static long cGbad_hdr;
        !           338: 
        !           339: /* Number of packets rejected because the checksum was bad.  */
        !           340: static long cGbad_checksum;
        !           341: 
        !           342: /* Number of packets received out of order.  */
        !           343: static long cGbad_order;
        !           344: 
        !           345: /* Number of packets rejected by receiver (number of RJ packets
        !           346:    received).  */
        !           347: static long cGremote_rejects;
        !           348: 
        !           349: /* The error level.  This is the total number of errors as adjusted by
        !           350:    cGerror_decay.  */
        !           351: static long cGerror_level;
        !           352: 
        !           353: /* Each time we send an RJ, we can expect several out of order of
        !           354:    packets, because the other side will probably have sent a full
        !           355:    window by the time it sees the RJ.  This variable keeps track of
        !           356:    the number of out of order packets we expect to see.  We don't
        !           357:    count expected out of order packets against the error level.  This
        !           358:    is reset to 0 when an in order packet is received.  */
        !           359: static int cGexpect_bad_order;
        !           360: 
        !           361: #if DEBUG > 1
        !           362: /* Control packet names used for debugging.  */
        !           363: static const char * const azGcontrol[] =
        !           364: {"?0?", "CLOSE", "RJ", "SRJ", "RR", "INITC", "INITB", "INITA"};
        !           365: #endif
        !           366: 
        !           367: /* Local functions.  */
        !           368: static boolean fgexchange_init P((struct sdaemon *qdaemon, int ictl,
        !           369:                                  int ival, int *piset));
        !           370: static boolean fgsend_control P((struct sdaemon *qdaemon, int ictl,
        !           371:                                 int ival));
        !           372: static char *zgadjust_ack P((int iseq));
        !           373: static boolean fgwait_for_packet P((struct sdaemon *qdaemon,
        !           374:                                    boolean freturncontrol, int ctimeout,
        !           375:                                    int cretries));
        !           376: static boolean fgsend_acks P((struct sdaemon *qdaemon));
        !           377: static boolean fggot_ack P((struct sdaemon *qdaemon, int iack));
        !           378: static boolean fgprocess_data P((struct sdaemon *qdaemon, boolean fdoacks,
        !           379:                                 boolean freturncontrol,
        !           380:                                 boolean *pfexit, size_t *pcneed,
        !           381:                                 boolean *pffound));
        !           382: static boolean fginit_sendbuffers P((boolean fallocate));
        !           383: static boolean fgcheck_errors P((struct sdaemon *qdaemon));
        !           384: static int igchecksum P((const char *zdata, size_t clen));
        !           385: static int igchecksum2 P((const char *zfirst, size_t cfirst,
        !           386:                          const char *zsecond, size_t csecond));
        !           387: 
        !           388: /* Start the protocol.  This requires a three way handshake.  Both sides
        !           389:    must send and receive an INITA packet, an INITB packet, and an INITC
        !           390:    packet.  The INITA and INITC packets contain the window size, and the
        !           391:    INITB packet contains the packet size.  */
        !           392: 
        !           393: boolean
        !           394: fgstart (qdaemon, pzlog)
        !           395:      struct sdaemon *qdaemon;
        !           396:      char **pzlog;
        !           397: {
        !           398:   int iseg;
        !           399:   int i;
        !           400:   boolean fgota, fgotb;
        !           401: 
        !           402:   *pzlog = NULL;
        !           403: 
        !           404:   /* The 'g' protocol requires a full eight bit interface.  */
        !           405:   if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
        !           406:                   STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
        !           407:     return FALSE;
        !           408: 
        !           409:   iGsendseq = 1;
        !           410:   iGremote_ack = 0;
        !           411:   iGretransmit_seq = -1;
        !           412:   iGrecseq = 0;
        !           413:   iGlocal_ack = 0;
        !           414:   cGsent_packets = 0;
        !           415:   cGresent_packets = 0;
        !           416:   cGdelayed_packets = 0;
        !           417:   cGrec_packets = 0;
        !           418:   cGbad_hdr = 0;
        !           419:   cGbad_checksum = 0;
        !           420:   cGbad_order = 0;
        !           421:   cGremote_rejects = 0;
        !           422:   cGerror_level = 0;
        !           423:   cGexpect_bad_order = 0;
        !           424: 
        !           425:   /* We must determine the segment size based on the packet size
        !           426:      which may have been modified by a protocol parameter command.
        !           427:      A segment size of 2^n is passed as n - 5.  */
        !           428:   i = iGrequest_packsize;
        !           429:   iseg = -1;
        !           430:   while (i > 0)
        !           431:     {
        !           432:       ++iseg;
        !           433:       i >>= 1;
        !           434:     }
        !           435:   iseg -= 5;
        !           436:   if (iseg < 0 || iseg > 7)
        !           437:     {
        !           438:       ulog (LOG_ERROR, "Illegal packet size %d for '%c' protocol",
        !           439:            iGrequest_packsize, qdaemon->qproto->bname);
        !           440:       iseg = 1;
        !           441:     }
        !           442:   
        !           443:   fgota = FALSE;
        !           444:   fgotb = FALSE;
        !           445:   for (i = 0; i < cGstartup_retries; i++)
        !           446:     {
        !           447:       if (fgota)
        !           448:        {
        !           449:          if (! fgsend_control (qdaemon, INITA, iGrequest_winsize))
        !           450:            return FALSE;
        !           451:        }
        !           452:       else
        !           453:        {
        !           454:          if (! fgexchange_init (qdaemon, INITA, iGrequest_winsize,
        !           455:                                 &iGremote_winsize))
        !           456:            continue;
        !           457:        }
        !           458:       fgota = TRUE;
        !           459: 
        !           460:       if (fgotb)
        !           461:        {
        !           462:          if (! fgsend_control (qdaemon, INITB, iseg))
        !           463:            return FALSE;
        !           464:        }
        !           465:       else
        !           466:        {
        !           467:          if (! fgexchange_init (qdaemon, INITB, iseg, &iGremote_segsize))
        !           468:            continue;
        !           469:        }
        !           470:       fgotb = TRUE;
        !           471: 
        !           472:       if (! fgexchange_init (qdaemon, INITC, iGrequest_winsize,
        !           473:                             &iGremote_winsize))
        !           474:        continue;
        !           475: 
        !           476:       /* We have succesfully connected.  Determine the remote packet
        !           477:         size.  */
        !           478:       iGremote_packsize = 1 << (iGremote_segsize + 5);
        !           479: 
        !           480:       /* If the user requested us to force specific remote window and
        !           481:         packet sizes, do so now.  */
        !           482:       if (iGforced_remote_winsize > 0
        !           483:          && iGforced_remote_winsize <= CMAXWINDOW)
        !           484:        iGremote_winsize = iGforced_remote_winsize;
        !           485: 
        !           486:       if (iGforced_remote_packsize >= 32
        !           487:          && iGforced_remote_packsize <= 4096)
        !           488:        {
        !           489:          /* Force the value to a power of two.  */
        !           490:          i = iGforced_remote_packsize;
        !           491:          iseg = -1;
        !           492:          while (i > 0)
        !           493:            {
        !           494:              ++iseg;
        !           495:              i >>= 1;
        !           496:            }
        !           497:          iGremote_packsize = 1 << iseg;
        !           498:          iGremote_segsize = iseg - 5;
        !           499:        }
        !           500: 
        !           501:       /* Set up packet buffers to use.  We don't do this until we know
        !           502:         the maximum packet size we are going to send.  */
        !           503:       if (! fginit_sendbuffers (TRUE))
        !           504:        return FALSE;
        !           505: 
        !           506:       *pzlog = zbufalc (sizeof "protocol '' packet size  window " + 50);
        !           507:       sprintf (*pzlog, "protocol '%c' packet size %d window %d",
        !           508:               qdaemon->qproto->bname, (int) iGremote_packsize,
        !           509:               (int) iGremote_winsize);
        !           510: 
        !           511:       return TRUE;
        !           512:     }
        !           513: 
        !           514:   DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !           515:                  "fgstart: Protocol startup failed");
        !           516: 
        !           517:   return FALSE;
        !           518: }
        !           519: 
        !           520: /* The 'G' protocol is identical to the 'g' protocol, except that
        !           521:    short packets are never supported.  */
        !           522: 
        !           523: boolean
        !           524: fbiggstart (qdaemon, pzlog)
        !           525:      struct sdaemon *qdaemon;
        !           526:      char **pzlog;
        !           527: {
        !           528:   fGshort_packets = FALSE;
        !           529:   return fgstart (qdaemon, pzlog);
        !           530: }
        !           531: 
        !           532: /* Exchange initialization messages with the other system.
        !           533: 
        !           534:    A problem:
        !           535: 
        !           536:    We send INITA; it gets received
        !           537:    We receive INITA
        !           538:    We send INITB; it gets garbled
        !           539:    We receive INITB
        !           540: 
        !           541:    We have seen and sent INITB, so we start to send INITC.  The other
        !           542:    side as sent INITB but not seen it, so it times out and resends
        !           543:    INITB.  We will continue sending INITC and the other side will
        !           544:    continue sending INITB until both sides give up and start again
        !           545:    with INITA.
        !           546: 
        !           547:    It might seem as though if we are sending INITC and receive INITB,
        !           548:    we should resend our INITB, but this could cause infinite echoing
        !           549:    of INITB on a long-latency line.  Rather than risk that, I have
        !           550:    implemented a fast drop-back procedure.  If we are sending INITB and
        !           551:    receive INITC, the other side has gotten ahead of us.  We immediately
        !           552:    fail and begin again with INITA.  For the other side, if we are
        !           553:    sending INITC and see INITA, we also immediately fail back to INITA.
        !           554: 
        !           555:    Unfortunately, this doesn't work for the other case, in which we
        !           556:    are sending INITB but the other side has not yet seen INITA.  As
        !           557:    far as I can see, if this happens we just have to wait until we
        !           558:    time out and resend INITA.  */
        !           559: 
        !           560: static boolean
        !           561: fgexchange_init (qdaemon, ictl, ival, piset)
        !           562:      struct sdaemon *qdaemon;
        !           563:      int ictl;
        !           564:      int ival;
        !           565:      int *piset;
        !           566: {
        !           567:   int i;
        !           568: 
        !           569:   /* The three-way handshake should be independent of who initializes
        !           570:      it, but it seems that some versions of uucico assume that the
        !           571:      caller sends first and the callee responds.  This only matters if
        !           572:      we are the callee and the first packet is garbled.  If we send a
        !           573:      packet, the other side will assume that we must have seen the
        !           574:      packet they sent and will never time out and send it again.
        !           575:      Therefore, if we are the callee we don't send a packet the first
        !           576:      time through the loop.  This can still fail, but should usually
        !           577:      work, and, after all, if the initialization packets are received
        !           578:      correctly there will be no problem no matter what we do.  */
        !           579:   for (i = 0; i < cGexchange_init_retries; i++)
        !           580:     {
        !           581:       long itime;
        !           582:       int ctimeout;
        !           583: 
        !           584:       if (qdaemon->fcaller || i > 0)
        !           585:        {
        !           586:          if (! fgsend_control (qdaemon, ictl, ival))
        !           587:            return FALSE;
        !           588:        }
        !           589: 
        !           590:       itime = ixsysdep_time ((long *) NULL);
        !           591:       ctimeout = cGexchange_init_timeout;
        !           592: 
        !           593:       do
        !           594:        {
        !           595:          long inewtime;
        !           596: 
        !           597:          /* We pass 0 as the retry count to fgwait_for_packet because
        !           598:             we want to handle retries here and because if it retried
        !           599:             it would send a packet, which would be bad.  */
        !           600:          if (! fgwait_for_packet (qdaemon, TRUE, ctimeout, 0))
        !           601:            break;
        !           602: 
        !           603:          if (CONTROL_TT (iGpacket_control) == CONTROL)
        !           604:            {
        !           605:              if (CONTROL_XXX (iGpacket_control) == ictl)
        !           606:                {
        !           607:                  *piset = CONTROL_YYY (iGpacket_control);
        !           608: 
        !           609:                  /* If we didn't already send our initialization
        !           610:                     packet, send it now.  */
        !           611:                  if (! qdaemon->fcaller && i == 0)
        !           612:                    {
        !           613:                      if (! fgsend_control (qdaemon, ictl, ival))
        !           614:                        return FALSE;
        !           615:                    }
        !           616: 
        !           617:                  return TRUE;
        !           618:                }
        !           619: 
        !           620:              /* If the other side is farther along than we are,
        !           621:                 we have lost a packet.  Fail immediately back to
        !           622:                 INITA (but don't fail if we are already doing INITA,
        !           623:                 since that would count against cStart_retries more
        !           624:                 than it should).  */
        !           625:              if (CONTROL_XXX (iGpacket_control) < ictl && ictl != INITA)
        !           626:                return FALSE;
        !           627: 
        !           628:              /* If we are sending INITC and we receive an INITA, the other
        !           629:                 side has failed back (we know this because we have
        !           630:                 seen an INITB from them).  Fail back ourselves to
        !           631:                 start the whole handshake over again.  */
        !           632:              if (CONTROL_XXX (iGpacket_control) == INITA && ictl == INITC)
        !           633:                return FALSE;
        !           634: 
        !           635:              /* As a special hack, if we are sending INITC and we
        !           636:                 receive INITB, we update the segment size from the
        !           637:                 packet.  This permits a second INITB to override the
        !           638:                 first one.  It would be nice to do this in a cleaner
        !           639:                 way.  */
        !           640:              if (CONTROL_XXX (iGpacket_control) == INITB && ictl == INITC)
        !           641:                iGremote_segsize = CONTROL_YYY (iGpacket_control);
        !           642:            }
        !           643: 
        !           644:          inewtime = ixsysdep_time ((long *) NULL);
        !           645:          ctimeout -= inewtime - itime;
        !           646:        }
        !           647:       while (ctimeout > 0);
        !           648:     }
        !           649: 
        !           650:   return FALSE;
        !           651: }
        !           652: 
        !           653: /* Shut down the protocol.  */
        !           654: 
        !           655: boolean
        !           656: fgshutdown (qdaemon)
        !           657:      struct sdaemon *qdaemon;
        !           658: {
        !           659:   (void) fgsend_control (qdaemon, CLOSE, 0);
        !           660:   (void) fgsend_control (qdaemon, CLOSE, 0);
        !           661:   (void) fginit_sendbuffers (FALSE);
        !           662: 
        !           663:   /* The count of sent packets may not be accurate, because some of
        !           664:      them may have not been sent yet if the connection failed in the
        !           665:      middle (the ones that counted for cGdelayed_packets).  I don't
        !           666:      think it's worth being precise.  */
        !           667:   ulog (LOG_NORMAL,
        !           668:        "Protocol '%c' packets: sent %ld, resent %ld, received %ld",
        !           669:        qdaemon->qproto->bname, cGsent_packets,
        !           670:        cGresent_packets - cGdelayed_packets, cGrec_packets);
        !           671:   if (cGbad_hdr != 0
        !           672:       || cGbad_checksum != 0
        !           673:       || cGbad_order != 0
        !           674:       || cGremote_rejects != 0)
        !           675:     ulog (LOG_NORMAL,
        !           676:          "Errors: header %ld, checksum %ld, order %ld, remote rejects %ld",
        !           677:          cGbad_hdr, cGbad_checksum, cGbad_order, cGremote_rejects);
        !           678: 
        !           679:   /* Reset all the parameters to their default values, so that the
        !           680:      protocol parameters used for this connection do not affect the
        !           681:      next one.  */
        !           682:   iGrequest_winsize = IWINDOW;
        !           683:   iGrequest_packsize = IPACKSIZE;
        !           684:   cGstartup_retries = CSTARTUP_RETRIES;
        !           685:   cGexchange_init_timeout = CEXCHANGE_INIT_TIMEOUT;
        !           686:   cGexchange_init_retries = CEXCHANGE_INIT_RETRIES;
        !           687:   cGtimeout = CTIMEOUT;
        !           688:   cGretries = CRETRIES;
        !           689:   cGgarbage_data = CGARBAGE;
        !           690:   cGmax_errors = CERRORS;
        !           691:   cGerror_decay = CERROR_DECAY;
        !           692:   iGforced_remote_winsize = IREMOTE_WINDOW;
        !           693:   iGforced_remote_packsize = IREMOTE_PACKSIZE;
        !           694:   fGshort_packets = TRUE;
        !           695: 
        !           696:   return TRUE;
        !           697: }
        !           698: 
        !           699: /* Send a command string.  We send packets containing the string until
        !           700:    the entire string has been sent.  Each packet is full.  */
        !           701: 
        !           702: /*ARGSUSED*/
        !           703: boolean
        !           704: fgsendcmd (qdaemon, z, ilocal, iremote)
        !           705:      struct sdaemon *qdaemon;
        !           706:      const char *z;
        !           707:      int ilocal;
        !           708:      int iremote;
        !           709: {
        !           710:   size_t clen;
        !           711:   boolean fagain;
        !           712: 
        !           713:   DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "fgsendcmd: Sending command \"%s\"", z);
        !           714: 
        !           715:   clen = strlen (z);
        !           716: 
        !           717:   do
        !           718:     {
        !           719:       char *zpacket;
        !           720:       size_t cdummy;
        !           721: 
        !           722:       zpacket = zggetspace (qdaemon, &cdummy);
        !           723: 
        !           724:       if (clen < iGremote_packsize)
        !           725:        {
        !           726:          size_t csize;
        !           727: 
        !           728:          /* If the remote packet size is larger than 64 (the default,
        !           729:             which may indicate an older UUCP package), try to fit
        !           730:             this command into a smaller packet.  We still always send
        !           731:             a complete packet, though.  */
        !           732:          if (iGremote_packsize <= 64 || ! fGshort_packets)
        !           733:            csize = iGremote_packsize;
        !           734:          else
        !           735:            {
        !           736:              csize = 32;
        !           737:              while (csize <= clen)
        !           738:                csize <<= 1;
        !           739:            }
        !           740: 
        !           741:          memcpy (zpacket, z, clen);
        !           742:          bzero (zpacket + clen, csize - clen);
        !           743:          fagain = FALSE;
        !           744: 
        !           745:          if (! fgsenddata (qdaemon, zpacket, csize, 0, 0, (long) 0))
        !           746:            return FALSE;
        !           747:        }
        !           748:       else
        !           749:        {
        !           750:          memcpy (zpacket, z, iGremote_packsize);
        !           751:          z += iGremote_packsize;
        !           752:          clen -= iGremote_packsize;
        !           753:          fagain = TRUE;
        !           754: 
        !           755:          if (! fgsenddata (qdaemon, zpacket, iGremote_packsize,
        !           756:                            0, 0, (long) 0))
        !           757:            return FALSE;
        !           758:        }
        !           759:     }
        !           760:   while (fagain);
        !           761: 
        !           762:   return TRUE;
        !           763: }
        !           764: 
        !           765: /* We keep an array of buffers to retransmit as necessary.  Rather
        !           766:    than waste static space on large buffer sizes, we allocate the
        !           767:    buffers once we know how large the other system expects them to be.
        !           768:    The sequence numbers used in the 'g' protocol are only three bits
        !           769:    long, so we allocate eight buffers and maintain a correspondence
        !           770:    between buffer index and sequence number.  This always wastes some
        !           771:    buffer space, but it's easy to implement.
        !           772: 
        !           773:    We leave room at the front of the buffer for the frame header and
        !           774:    two additional bytes.  The two extra bytes are used for short
        !           775:    packets, which essentially use a longer header and shorter data.
        !           776:    We do this to avoid moving the data.  We zero out any unused bytes
        !           777:    before the frame, so we can locate the real header given a buffer
        !           778:    by finding the first non-zero byte (which will be one of the first
        !           779:    three bytes in the buffer).  */
        !           780: 
        !           781: #define CSENDBUFFERS (CMAXWINDOW + 1)
        !           782: 
        !           783: static char *azGsendbuffers[CSENDBUFFERS];
        !           784: 
        !           785: static boolean
        !           786: fginit_sendbuffers (fallocate)
        !           787:      boolean fallocate;
        !           788: {
        !           789:   int i;
        !           790: 
        !           791:   /* Free up any remaining old buffers.  */
        !           792:   for (i = 0; i < CSENDBUFFERS; i++)
        !           793:     {
        !           794:       xfree ((pointer) azGsendbuffers[i]);
        !           795:       if (fallocate)
        !           796:        {
        !           797:          azGsendbuffers[i] = (char *) malloc (CFRAMELEN + 2
        !           798:                                               + iGremote_packsize);
        !           799:          if (azGsendbuffers[i] == NULL)
        !           800:            return FALSE;
        !           801: 
        !           802:          /* This bzero might not seem necessary, since before we send
        !           803:             out each packet we zero out any non-data bytes.  However,
        !           804:             if we receive an SRJ at the start of the conversation, we
        !           805:             will send out the packet before it has been set to
        !           806:             anything, thus sending the contents of our heap.  We
        !           807:             avoid this by using bzero.  */
        !           808:          bzero (azGsendbuffers[i], CFRAMELEN + 2 + iGremote_packsize);
        !           809:        }
        !           810:       else
        !           811:        azGsendbuffers[i] = NULL;
        !           812:     }
        !           813:   return TRUE;
        !           814: }
        !           815: 
        !           816: /* Allocate a packet to send out.  The return value of this function
        !           817:    must be filled in and passed to fgsenddata, or discarded.  This
        !           818:    will ensure that the buffers and iGsendseq stay in synch.  Set
        !           819:    *pclen to the amount of data to place in the buffer.  */
        !           820: 
        !           821: /*ARGSUSED*/
        !           822: char *
        !           823: zggetspace (qdaemon, pclen)
        !           824:      struct sdaemon *qdaemon;
        !           825:      size_t *pclen;
        !           826: {
        !           827:   *pclen = iGremote_packsize;
        !           828:   return azGsendbuffers[iGsendseq] + CFRAMELEN + 2;
        !           829: }
        !           830: 
        !           831: /* Send out a data packet.  This computes the checksum, sets up the
        !           832:    header, and sends the packet out.  The argument zdata should point
        !           833:    to the return value of zggetspace.  */
        !           834: 
        !           835: /*ARGSIGNORED*/
        !           836: boolean
        !           837: fgsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
        !           838:      struct sdaemon *qdaemon;
        !           839:      char *zdata;
        !           840:      size_t cdata;
        !           841:      int ilocal;
        !           842:      int iremote;
        !           843:      long ipos;
        !           844: {
        !           845:   char *z;
        !           846:   int itt, iseg;
        !           847:   size_t csize;
        !           848:   int iclr1, iclr2;
        !           849:   unsigned short icheck;
        !           850: 
        !           851:   /* Set the initial length bytes.  See the description at the definition
        !           852:      of SHORTDATA, above.  */
        !           853:   itt = DATA;
        !           854:   csize = iGremote_packsize;
        !           855:   iseg = iGremote_segsize + 1;
        !           856: 
        !           857: #if DEBUG > 0
        !           858:   if (cdata > csize)
        !           859:     ulog (LOG_FATAL, "fgsend_packet: Packet size too large");
        !           860: #endif
        !           861: 
        !           862:   iclr1 = -1;
        !           863:   iclr2 = -2;
        !           864:   if (cdata < csize)
        !           865:     {
        !           866:       /* If the remote packet size is larger than 64, the default, we
        !           867:         can assume they can handle a smaller packet as well, which
        !           868:         will be more efficient to send.  */
        !           869:       if (iGremote_packsize > 64 && fGshort_packets)
        !           870:        {
        !           871:          /* The packet size is 1 << (iseg + 4).  */
        !           872:          iseg = 1;
        !           873:          csize = 32;
        !           874:          while (csize < cdata)
        !           875:            {
        !           876:              csize <<= 1;
        !           877:              ++iseg;
        !           878:            }
        !           879:        }
        !           880: 
        !           881:       if (csize != cdata)
        !           882:        {
        !           883:          size_t cshort;
        !           884: 
        !           885:          /* We have to add bytes which indicate how short the packet
        !           886:             is.  We do this by pushing the header backward, which we
        !           887:             can do because we allocated two extra bytes for this
        !           888:             purpose.  */
        !           889:          iclr2 = 0;
        !           890:          itt = SHORTDATA;
        !           891:          cshort = csize - cdata;
        !           892:          if (cshort <= 127)
        !           893:            {
        !           894:              --zdata;
        !           895:              zdata[0] = (char) cshort;
        !           896:              zdata[-1] = '\0';
        !           897:              bzero (zdata + cdata + 1, cshort - 1);
        !           898:            }
        !           899:          else
        !           900:            {
        !           901:              zdata -= 2;
        !           902:              zdata[0] = (char) (0x80 | (cshort & 0x7f));
        !           903:              zdata[1] = (char) (cshort >> 7);
        !           904:              bzero (zdata + cdata + 2, cshort - 2);
        !           905:              iclr1 = 0;
        !           906:            }
        !           907:        }
        !           908:     }
        !           909: 
        !           910:   z = zdata - CFRAMELEN;
        !           911: 
        !           912:   /* Zero out the preceding bytes, in case the last time this buffer
        !           913:      was used those bytes were used.  We need to zero out the initial
        !           914:      bytes so that we can find the true start of the packet in
        !           915:      zgadjust_ack.  */
        !           916:   z[iclr1] = '\0';
        !           917:   z[iclr2] = '\0';
        !           918: 
        !           919:   z[IFRAME_DLE] = DLE;
        !           920:   z[IFRAME_K] = (char) iseg;
        !           921: 
        !           922:   icheck = (unsigned short) igchecksum (zdata, csize);
        !           923: 
        !           924:   /* We're just about ready to go.  Wait until there is room in the
        !           925:      receiver's window for us to send the packet.  We do this now so
        !           926:      that we send the correct value for the last packet received.
        !           927:      Note that if iGsendseq == iGremote_ack, this means that the
        !           928:      sequence numbers are actually 8 apart, since the packet could not
        !           929:      have been acknowledged before it was sent; this can happen when
        !           930:      the window size is 7.  */
        !           931:   while (iGsendseq == iGremote_ack
        !           932:         || CSEQDIFF (iGsendseq, iGremote_ack) > iGremote_winsize)
        !           933:     {
        !           934:       if (! fgwait_for_packet (qdaemon, TRUE, cGtimeout, cGretries))
        !           935:        return FALSE;
        !           936:     }
        !           937: 
        !           938:   /* Ack all packets up to the next one, since the UUCP protocol
        !           939:      requires that all packets be acked in order.  */
        !           940:   while (CSEQDIFF (iGrecseq, iGlocal_ack) > 1)
        !           941:     {
        !           942:       iGlocal_ack = INEXTSEQ (iGlocal_ack);
        !           943:       if (! fgsend_control (qdaemon, RR, iGlocal_ack))
        !           944:        return FALSE;
        !           945:     }
        !           946:   iGlocal_ack = iGrecseq;
        !           947: 
        !           948:   z[IFRAME_CONTROL] = (char) ((itt << 6) | (iGsendseq << 3) | iGrecseq);
        !           949: 
        !           950:   iGsendseq = INEXTSEQ (iGsendseq);
        !           951: 
        !           952:   icheck = ((unsigned short)
        !           953:            ((0xaaaa - (icheck ^ (z[IFRAME_CONTROL] & 0xff))) & 0xffff));
        !           954:   z[IFRAME_CHECKLOW] = (char) (icheck & 0xff);
        !           955:   z[IFRAME_CHECKHIGH] = (char) (icheck >> 8);
        !           956: 
        !           957:   z[IFRAME_XOR] = (char) (z[IFRAME_K] ^ z[IFRAME_CHECKLOW]
        !           958:                          ^ z[IFRAME_CHECKHIGH] ^ z[IFRAME_CONTROL]);
        !           959: 
        !           960:   /* If we're waiting for acks of retransmitted packets, then don't
        !           961:      send this packet yet.  The other side may not be ready for it
        !           962:      yet.  Instead, code in fggot_ack will send the outstanding
        !           963:      packets when an ack is received.  */
        !           964:   ++cGsent_packets;
        !           965: 
        !           966:   if (iGretransmit_seq != -1)
        !           967:     {
        !           968:       ++cGdelayed_packets;
        !           969:       return TRUE;
        !           970:     }
        !           971: 
        !           972:   DEBUG_MESSAGE2 (DEBUG_PROTO,
        !           973:                  "fgsenddata: Sending packet %d (%d bytes)",
        !           974:                  CONTROL_XXX (z[IFRAME_CONTROL]), cdata);
        !           975: 
        !           976:   return fsend_data (qdaemon->qconn, z, CFRAMELEN + csize, TRUE);
        !           977: }
        !           978: 
        !           979: /* Recompute the control byte and checksum of a packet so that it
        !           980:    includes the correct packet acknowledgement.  This is called when a
        !           981:    packet is retransmitted to make sure the retransmission does not
        !           982:    confuse the other side.  It returns a pointer to the start of the
        !           983:    packet, skipping the bytes that may be unused at the start of
        !           984:    azGsendbuffers[iseq].  */
        !           985: 
        !           986: static char *
        !           987: zgadjust_ack (iseq)
        !           988:      int iseq;
        !           989: {
        !           990:   register char *z;
        !           991:   unsigned short icheck;
        !           992: 
        !           993:   z = azGsendbuffers[iseq];
        !           994:   if (*z == '\0')
        !           995:     ++z;
        !           996:   if (*z == '\0')
        !           997:     ++z;
        !           998: 
        !           999:   /* If the received packet number is the same, there is nothing
        !          1000:      to do.  */
        !          1001:   if (CONTROL_YYY (z[IFRAME_CONTROL]) == iGrecseq)
        !          1002:     return z;
        !          1003: 
        !          1004:   /* Get the old checksum.  */
        !          1005:   icheck = (unsigned short) (((z[IFRAME_CHECKHIGH] & 0xff) << 8)
        !          1006:                             | (z[IFRAME_CHECKLOW] & 0xff));
        !          1007:   icheck = ((unsigned short)
        !          1008:            (((0xaaaa - icheck) ^ (z[IFRAME_CONTROL] & 0xff)) & 0xffff));
        !          1009: 
        !          1010:   /* Update the control byte.  */
        !          1011:   z[IFRAME_CONTROL] = (char) ((z[IFRAME_CONTROL] &~ 07) | iGrecseq);
        !          1012: 
        !          1013:   /* Create the new checksum.  */
        !          1014:   icheck = ((unsigned short)
        !          1015:            ((0xaaaa - (icheck ^ (z[IFRAME_CONTROL] & 0xff))) & 0xffff));
        !          1016:   z[IFRAME_CHECKLOW] = (char) (icheck & 0xff);
        !          1017:   z[IFRAME_CHECKHIGH] = (char) (icheck >> 8);
        !          1018: 
        !          1019:   /* Update the XOR byte.  */
        !          1020:   z[IFRAME_XOR] = (char) (z[IFRAME_K] ^ z[IFRAME_CHECKLOW]
        !          1021:                          ^ z[IFRAME_CHECKHIGH] ^ z[IFRAME_CONTROL]);
        !          1022: 
        !          1023:   return z;
        !          1024: }
        !          1025: 
        !          1026: /* Send a control packet.  These are fairly simple to construct.  It
        !          1027:    seems reasonable to me that we should be able to send a control
        !          1028:    packet at any time, even if the receive window is closed.  In
        !          1029:    particular, we don't want to delay when sending a CLOSE control
        !          1030:    message.  If I'm wrong, it can be changed easily enough.  */
        !          1031: 
        !          1032: static boolean
        !          1033: fgsend_control (qdaemon, ixxx, iyyy)
        !          1034:      struct sdaemon *qdaemon;
        !          1035:      int ixxx;
        !          1036:      int iyyy;
        !          1037: {
        !          1038:   char ab[CFRAMELEN];
        !          1039:   int ictl;
        !          1040:   unsigned short icheck;
        !          1041: 
        !          1042: #if DEBUG > 1
        !          1043:   if (FDEBUGGING (DEBUG_PROTO) ||
        !          1044:       (FDEBUGGING (DEBUG_ABNORMAL) && ixxx != RR))
        !          1045:     ulog (LOG_DEBUG, "fgsend_control: Sending control %s %d",
        !          1046:          azGcontrol[ixxx], iyyy);
        !          1047: #endif
        !          1048: 
        !          1049:   ab[IFRAME_DLE] = DLE;
        !          1050:   ab[IFRAME_K] = KCONTROL;
        !          1051: 
        !          1052:   ictl = (CONTROL << 6) | (ixxx << 3) | iyyy;
        !          1053:   icheck = (unsigned short) (0xaaaa - ictl);
        !          1054:   ab[IFRAME_CHECKLOW] = (char) (icheck & 0xff);
        !          1055:   ab[IFRAME_CHECKHIGH] = (char) (icheck >> 8);
        !          1056: 
        !          1057:   ab[IFRAME_CONTROL] = (char) ictl;
        !          1058: 
        !          1059:   ab[IFRAME_XOR] = (char) (ab[IFRAME_K] ^ ab[IFRAME_CHECKLOW]
        !          1060:                           ^ ab[IFRAME_CHECKHIGH] ^ ab[IFRAME_CONTROL]);
        !          1061: 
        !          1062:   return fsend_data (qdaemon->qconn, ab, (size_t) CFRAMELEN, TRUE);
        !          1063: }
        !          1064: 
        !          1065: /* Wait for data to come in.  This continues processing until a
        !          1066:    complete file or command has been received.  */
        !          1067: 
        !          1068: boolean
        !          1069: fgwait (qdaemon)
        !          1070:      struct sdaemon *qdaemon;
        !          1071: {
        !          1072:   return fgwait_for_packet (qdaemon, FALSE, cGtimeout, cGretries);
        !          1073: }
        !          1074: 
        !          1075: /* Get a packet.  This is called when we have nothing to send, but
        !          1076:    want to wait for a packet to come in.  If freturncontrol is TRUE,
        !          1077:    this will return after getting any control packet.  Otherwise, it
        !          1078:    will continue to receive packets until a complete file or a
        !          1079:    complete command has been received.  The timeout and the number of
        !          1080:    retries are specified as arguments.  The function returns FALSE if
        !          1081:    an error occurs or if cretries timeouts of ctimeout seconds were
        !          1082:    exceeded.  */
        !          1083: 
        !          1084: static boolean
        !          1085: fgwait_for_packet (qdaemon, freturncontrol, ctimeout, cretries)
        !          1086:      struct sdaemon *qdaemon;
        !          1087:      boolean freturncontrol;
        !          1088:      int ctimeout;
        !          1089:      int cretries;
        !          1090: {
        !          1091:   int ctimeouts;
        !          1092:   int cgarbage;
        !          1093:   int cshort;
        !          1094: 
        !          1095:   ctimeouts = 0;
        !          1096:   cgarbage = 0;
        !          1097:   cshort = 0;
        !          1098: 
        !          1099:   while (TRUE)
        !          1100:     {
        !          1101:       boolean fexit;
        !          1102:       size_t cneed;
        !          1103:       boolean ffound;
        !          1104:       size_t crec;
        !          1105:   
        !          1106:       if (! fgprocess_data (qdaemon, TRUE, freturncontrol, &fexit,
        !          1107:                            &cneed, &ffound))
        !          1108:        return FALSE;
        !          1109: 
        !          1110:       if (fexit)
        !          1111:        return TRUE;
        !          1112: 
        !          1113:       DEBUG_MESSAGE1 (DEBUG_PROTO,
        !          1114:                      "fgwait_for_packet: Need %lu bytes",
        !          1115:                      (unsigned long) cneed);
        !          1116: 
        !          1117:       if (ffound)
        !          1118:        {
        !          1119:          ctimeouts = 0;
        !          1120:          cgarbage = 0;
        !          1121:        }
        !          1122:       else
        !          1123:        {
        !          1124:          if (cgarbage > cGgarbage_data)
        !          1125:            {
        !          1126:              ulog (LOG_ERROR, "Too much unrecognized data");
        !          1127:              return FALSE;
        !          1128:            }
        !          1129:        }
        !          1130: 
        !          1131:       if (! freceive_data (qdaemon->qconn, cneed, &crec, ctimeout, TRUE))
        !          1132:        return FALSE;
        !          1133: 
        !          1134:       cgarbage += crec;
        !          1135: 
        !          1136:       if (crec != 0)
        !          1137:        {
        !          1138:          /* If we don't get enough data twice in a row, we may have
        !          1139:             dropped some data and still be looking for the end of a
        !          1140:             large packet.  Incrementing iPrecstart will force
        !          1141:             fgprocess_data to skip that packet and look through the
        !          1142:             rest of the data.  In some situations, this will be a
        !          1143:             mistake.  */
        !          1144:          if (crec >= cneed)
        !          1145:            cshort = 0;
        !          1146:          else
        !          1147:            {
        !          1148:              ++cshort;
        !          1149:              if (cshort > 1)
        !          1150:                {
        !          1151:                  iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
        !          1152:                  cshort = 0;
        !          1153:                }
        !          1154:            }
        !          1155:        }
        !          1156:       else
        !          1157:        {
        !          1158:          /* The read timed out.  If we have an unacknowledged packet,
        !          1159:             send it again.  Otherwise, send an RJ with the last
        !          1160:             packet we received correctly.  */
        !          1161:          ++ctimeouts;
        !          1162:          if (ctimeouts > cretries)
        !          1163:            {
        !          1164:              if (cretries > 0)
        !          1165:                ulog (LOG_ERROR, "Timed out waiting for packet");
        !          1166:              return FALSE;
        !          1167:            }
        !          1168: 
        !          1169:          if (INEXTSEQ (iGremote_ack) != iGsendseq)
        !          1170:            {
        !          1171:              int inext;
        !          1172:              char *zsend;
        !          1173: 
        !          1174:              inext = INEXTSEQ (iGremote_ack);
        !          1175: 
        !          1176:              DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1177:                              "fgwait_for_packet: Resending packet %d",
        !          1178:                              inext);
        !          1179: 
        !          1180:              ++cGresent_packets;
        !          1181:              zsend = zgadjust_ack (inext);
        !          1182:              if (! fsend_data (qdaemon->qconn, zsend,
        !          1183:                                CFRAMELEN + CPACKLEN (zsend), TRUE))
        !          1184:                return FALSE;
        !          1185:              iGretransmit_seq = inext;
        !          1186:            }
        !          1187:          else
        !          1188:            {
        !          1189:              /* Send all pending acks first, to avoid confusing
        !          1190:                 the other side.  */
        !          1191:              if (iGlocal_ack != iGrecseq)
        !          1192:                {
        !          1193:                  if (! fgsend_acks (qdaemon))
        !          1194:                    return FALSE;
        !          1195:                }
        !          1196:              if (! fgsend_control (qdaemon, RJ, iGrecseq))
        !          1197:                return FALSE;
        !          1198:            }
        !          1199:        }
        !          1200:     }
        !          1201: }
        !          1202: 
        !          1203: /* Send acks for all packets we haven't acked yet.  */
        !          1204: 
        !          1205: static boolean
        !          1206: fgsend_acks (qdaemon)
        !          1207:      struct sdaemon *qdaemon;
        !          1208: {
        !          1209:   while (iGlocal_ack != iGrecseq)
        !          1210:     {
        !          1211:       iGlocal_ack = INEXTSEQ (iGlocal_ack);
        !          1212:       if (! fgsend_control (qdaemon, RR, iGlocal_ack))
        !          1213:        return FALSE;
        !          1214:     }
        !          1215:   return TRUE;
        !          1216: }
        !          1217: 
        !          1218: /* Handle an ack of a packet.  According to Hanrahan's paper, this
        !          1219:    acknowledges all previous packets.  If this is an ack for a
        !          1220:    retransmitted packet, continue by resending up to two more packets
        !          1221:    following the retransmitted one.  This should recover quickly from
        !          1222:    a line glitch, while avoiding the problem of continual
        !          1223:    retransmission.  */
        !          1224: 
        !          1225: static boolean
        !          1226: fggot_ack (qdaemon, iack)
        !          1227:      struct sdaemon *qdaemon;
        !          1228:      int iack;
        !          1229: {
        !          1230:   int inext;
        !          1231:   char *zsend;
        !          1232: 
        !          1233:   /* We only decrement the error level if we are not retransmitting
        !          1234:      packets.  We want to catch a sudden downgrade in line quality as
        !          1235:      fast as possible.  */
        !          1236:   if (cGerror_level > 0
        !          1237:       && iGretransmit_seq == -1
        !          1238:       && cGsent_packets % cGerror_decay == 0)
        !          1239:     --cGerror_level;
        !          1240:   cGexpect_bad_order = 0;
        !          1241: 
        !          1242:   /* Each time packet 0 is acknowledged, we call uwindow_acked since a
        !          1243:      new window has been acked.  */
        !          1244:   if (iack < iGremote_ack)
        !          1245:     uwindow_acked (qdaemon, FALSE);
        !          1246: 
        !          1247:   iGremote_ack = iack;
        !          1248: 
        !          1249:   if (iGretransmit_seq == -1)
        !          1250:     return TRUE;
        !          1251: 
        !          1252:   inext = INEXTSEQ (iGretransmit_seq);
        !          1253:   if (inext == iGsendseq)
        !          1254:     iGretransmit_seq = -1;
        !          1255:   else
        !          1256:     {
        !          1257:       DEBUG_MESSAGE1 (DEBUG_PROTO,
        !          1258:                      "fggot_ack: Sending packet %d", inext);
        !          1259: 
        !          1260:       ++cGresent_packets;
        !          1261:       zsend = zgadjust_ack (inext);
        !          1262:       if (! fsend_data (qdaemon->qconn, zsend, CFRAMELEN + CPACKLEN (zsend),
        !          1263:                        TRUE))
        !          1264:        return FALSE;
        !          1265:       inext = INEXTSEQ (inext);
        !          1266:       if (inext == iGsendseq)
        !          1267:        iGretransmit_seq = -1;
        !          1268:       else
        !          1269:        {
        !          1270:          DEBUG_MESSAGE1 (DEBUG_PROTO,
        !          1271:                          "fggot_ack: Sending packet %d", inext);
        !          1272: 
        !          1273:          ++cGresent_packets;
        !          1274:          zsend = zgadjust_ack (inext);
        !          1275:          if (! fsend_data (qdaemon->qconn, zsend,
        !          1276:                            CFRAMELEN + CPACKLEN (zsend), TRUE))
        !          1277:            return FALSE;
        !          1278:          iGretransmit_seq = inext;
        !          1279:        }
        !          1280:     }
        !          1281: 
        !          1282:   return TRUE;
        !          1283: }
        !          1284: 
        !          1285: /* See if we've received more than the permitted number of errors.  If
        !          1286:    we receive a bad packet, we can expect a window full (less one) of
        !          1287:    out of order packets to follow, so we discount cGbad_order
        !          1288:    accordingly.  */
        !          1289: 
        !          1290: static boolean
        !          1291: fgcheck_errors (qdaemon)
        !          1292:      struct sdaemon *qdaemon;
        !          1293: {
        !          1294:   if (cGerror_level > cGmax_errors && cGmax_errors >= 0)
        !          1295:     {
        !          1296:       ulog (LOG_ERROR, "Too many '%c' protocol errors",
        !          1297:            qdaemon->qproto->bname);
        !          1298:       return FALSE;
        !          1299:     }
        !          1300: 
        !          1301:   return TRUE;
        !          1302: }
        !          1303: 
        !          1304: /* Process the receive buffer into a data packet, if possible.  All
        !          1305:    control packets are handled here.  When a data packet is received,
        !          1306:    fgprocess_data calls fgot_data with the data; if that sets its
        !          1307:    pfexit argument to TRUE fgprocess_data will set *pfexit to TRUE and
        !          1308:    return TRUE.  Also, if the freturncontrol argument is TRUE
        !          1309:    fgprocess_data will set *pfexit to TRUE and return TRUE.  Otherwise
        !          1310:    fgprocess_data will continue trying to process data.  If some error
        !          1311:    occurs, fgprocess_data will return FALSE.  If there is not enough
        !          1312:    data to form a complete packet, then *pfexit will be set to FALSE,
        !          1313:    *pcneed will be set to the number of bytes needed to form a
        !          1314:    complete packet (unless pcneed is NULL) and fgprocess_data will
        !          1315:    return TRUE.  If this function found a data packet, and pffound is
        !          1316:    not NULL, it will set *pffound to TRUE; this can be used to tell
        !          1317:    valid data from an endless stream of garbage and control packets.
        !          1318:    If fdoacks is TRUE, received packets will be acknowledged;
        !          1319:    otherwise they must be acknowledged later.  */
        !          1320: 
        !          1321: static boolean
        !          1322: fgprocess_data (qdaemon, fdoacks, freturncontrol, pfexit, pcneed, pffound)
        !          1323:      struct sdaemon *qdaemon;
        !          1324:      boolean fdoacks;
        !          1325:      boolean freturncontrol;
        !          1326:      boolean *pfexit;
        !          1327:      size_t *pcneed;
        !          1328:      boolean *pffound;
        !          1329: {
        !          1330:   *pfexit = FALSE;
        !          1331:   if (pffound != NULL)
        !          1332:     *pffound = FALSE;
        !          1333: 
        !          1334:   while (iPrecstart != iPrecend)
        !          1335:     {
        !          1336:       char ab[CFRAMELEN];
        !          1337:       int i, iget, cwant;
        !          1338:       unsigned short ihdrcheck, idatcheck;
        !          1339:       const char *zfirst, *zsecond;
        !          1340:       int cfirst, csecond;
        !          1341:       boolean fduprr;
        !          1342: 
        !          1343:       /* Look for the DLE which must start a packet.  */
        !          1344:       if (abPrecbuf[iPrecstart] != DLE)
        !          1345:        {
        !          1346:          char *zdle;
        !          1347: 
        !          1348:          cfirst = iPrecend - iPrecstart;
        !          1349:          if (cfirst < 0)
        !          1350:            cfirst = CRECBUFLEN - iPrecstart;
        !          1351: 
        !          1352:          zdle = memchr (abPrecbuf + iPrecstart, DLE, (size_t) cfirst);
        !          1353: 
        !          1354:          if (zdle == NULL)
        !          1355:            {
        !          1356:              iPrecstart = (iPrecstart + cfirst) % CRECBUFLEN;
        !          1357:              continue;
        !          1358:            }
        !          1359: 
        !          1360:          /* We don't need % CRECBUFLEN here because zdle - (abPrecbuf
        !          1361:             + iPrecstart) < cfirst <= CRECBUFLEN - iPrecstart.  */
        !          1362:          iPrecstart += zdle - (abPrecbuf + iPrecstart);
        !          1363:        }
        !          1364: 
        !          1365:       /* Get the first six bytes into ab.  */
        !          1366:       for (i = 0, iget = iPrecstart;
        !          1367:           i < CFRAMELEN && iget != iPrecend;
        !          1368:           i++, iget = (iget + 1) % CRECBUFLEN)
        !          1369:        ab[i] = abPrecbuf[iget];
        !          1370: 
        !          1371:       /* If there aren't six bytes, there is no packet.  */
        !          1372:       if (i < CFRAMELEN)
        !          1373:        {
        !          1374:          if (pcneed != NULL)
        !          1375:            *pcneed = CFRAMELEN - i;
        !          1376:          return TRUE;
        !          1377:        }
        !          1378: 
        !          1379:       /* Make sure these six bytes start a packet.  The check on
        !          1380:         IFRAME_DLE is basically a debugging check, since the above
        !          1381:         code should have ensured that it will never fail.  If this is
        !          1382:         not the start of a packet, bump iPrecstart and loop around to
        !          1383:         look for another DLE.  */
        !          1384:       if (ab[IFRAME_DLE] != DLE
        !          1385:          || ab[IFRAME_K] < 1
        !          1386:          || ab[IFRAME_K] > 9
        !          1387:          || ab[IFRAME_XOR] != (ab[IFRAME_K] ^ ab[IFRAME_CHECKLOW]
        !          1388:                                ^ ab[IFRAME_CHECKHIGH] ^ ab[IFRAME_CONTROL])
        !          1389:          || CONTROL_TT (ab[IFRAME_CONTROL]) == ALTCHAN)
        !          1390:        {
        !          1391:          ++cGbad_hdr;
        !          1392:          ++cGerror_level;
        !          1393: 
        !          1394:          DEBUG_MESSAGE4 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1395:                          "fgprocess_data: Bad header: K %d TT %d XOR byte %d calc %d",
        !          1396:                          ab[IFRAME_K] & 0xff,
        !          1397:                          CONTROL_TT (ab[IFRAME_CONTROL]),
        !          1398:                          ab[IFRAME_XOR] & 0xff,
        !          1399:                          (ab[IFRAME_K]
        !          1400:                           ^ ab[IFRAME_CHECKLOW]
        !          1401:                           ^ ab[IFRAME_CHECKHIGH]
        !          1402:                           ^ ab[IFRAME_CONTROL]) & 0xff);
        !          1403: 
        !          1404:          if (! fgcheck_errors (qdaemon))
        !          1405:            return FALSE;
        !          1406: 
        !          1407:          iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
        !          1408:          continue;
        !          1409:        }
        !          1410: 
        !          1411:       /* The zfirst and cfirst pair point to the first set of data for
        !          1412:         this packet; the zsecond and csecond point to the second set,
        !          1413:         in case the packet wraps around the end of the buffer.  */
        !          1414:       zfirst = abPrecbuf + iPrecstart + CFRAMELEN;
        !          1415:       cfirst = 0;
        !          1416:       zsecond = NULL;
        !          1417:       csecond = 0;
        !          1418: 
        !          1419:       if (ab[IFRAME_K] == KCONTROL)
        !          1420:        {
        !          1421:          /* This is a control packet.  It should not have any data.  */
        !          1422:          if (CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL)
        !          1423:            {
        !          1424:              ++cGbad_hdr;
        !          1425:              ++cGerror_level;
        !          1426: 
        !          1427:              DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1428:                              "fgprocess_data: Bad header: control packet with data");
        !          1429: 
        !          1430:              if (! fgcheck_errors (qdaemon))
        !          1431:                return FALSE;
        !          1432: 
        !          1433:              iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
        !          1434:              continue;
        !          1435:            }
        !          1436: 
        !          1437:          idatcheck = (unsigned short) (0xaaaa - ab[IFRAME_CONTROL]);
        !          1438:          cwant = 0;
        !          1439:        }
        !          1440:       else
        !          1441:        {
        !          1442:          int cinbuf;
        !          1443:          unsigned short icheck;
        !          1444: 
        !          1445:          /* This is a data packet.  It should not be type CONTROL.  */
        !          1446:          if (CONTROL_TT (ab[IFRAME_CONTROL]) == CONTROL)
        !          1447:            {
        !          1448:              ++cGbad_hdr;
        !          1449:              ++cGerror_level;
        !          1450: 
        !          1451:              DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1452:                              "fgprocess_data: Bad header: data packet is type CONTROL");
        !          1453: 
        !          1454:              if (! fgcheck_errors (qdaemon))
        !          1455:                return FALSE;
        !          1456: 
        !          1457:              iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
        !          1458:              continue;
        !          1459:            }
        !          1460: 
        !          1461:          cinbuf = iPrecend - iPrecstart;
        !          1462:          if (cinbuf < 0)
        !          1463:            cinbuf += CRECBUFLEN;
        !          1464:          cinbuf -= CFRAMELEN;
        !          1465: 
        !          1466:          /* Make sure we have enough data.  If we don't, wait for
        !          1467:             more.  */       
        !          1468: 
        !          1469:          cwant = (int) CPACKLEN (ab);
        !          1470:          if (cinbuf < cwant)
        !          1471:            {
        !          1472:              if (pcneed != NULL)
        !          1473:                *pcneed = cwant - cinbuf;
        !          1474:              return TRUE;
        !          1475:            }
        !          1476:          
        !          1477:          /* Set up the data pointers and compute the checksum.  */
        !          1478:          if (iPrecend >= iPrecstart)
        !          1479:            cfirst = cwant;
        !          1480:          else
        !          1481:            {
        !          1482:              cfirst = CRECBUFLEN - (iPrecstart + CFRAMELEN);
        !          1483:              if (cfirst >= cwant)
        !          1484:                cfirst = cwant;
        !          1485:              else if (cfirst > 0)
        !          1486:                {
        !          1487:                  zsecond = abPrecbuf;
        !          1488:                  csecond = cwant - cfirst;
        !          1489:                }
        !          1490:              else
        !          1491:                {
        !          1492:                  /* Here cfirst is non-positive, so subtracting from
        !          1493:                     abPrecbuf will actually skip the appropriate number
        !          1494:                     of bytes at the start of abPrecbuf.  */
        !          1495:                  zfirst = abPrecbuf - cfirst;
        !          1496:                  cfirst = cwant;
        !          1497:                }
        !          1498:            }
        !          1499: 
        !          1500:          if (csecond == 0)
        !          1501:            icheck = (unsigned short) igchecksum (zfirst, (size_t) cfirst);
        !          1502:          else
        !          1503:            icheck = (unsigned short) igchecksum2 (zfirst, (size_t) cfirst,
        !          1504:                                                   zsecond,
        !          1505:                                                   (size_t) csecond);
        !          1506: 
        !          1507:          idatcheck = ((unsigned short)
        !          1508:                       (((0xaaaa - (icheck ^ (ab[IFRAME_CONTROL] & 0xff)))
        !          1509:                         & 0xffff)));
        !          1510:        }
        !          1511:       
        !          1512:       ihdrcheck = (unsigned short) (((ab[IFRAME_CHECKHIGH] & 0xff) << 8)
        !          1513:                                    | (ab[IFRAME_CHECKLOW] & 0xff));
        !          1514: 
        !          1515:       if (ihdrcheck != idatcheck)
        !          1516:        {
        !          1517:          DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1518:                          "fgprocess_data: Bad checksum: header 0x%x, data 0x%x",
        !          1519:                          ihdrcheck, idatcheck);
        !          1520: 
        !          1521:          ++cGbad_checksum;
        !          1522:          ++cGerror_level;
        !          1523: 
        !          1524:          if (! fgcheck_errors (qdaemon))
        !          1525:            return FALSE;
        !          1526: 
        !          1527:          /* If the checksum failed for a data packet, then if it was
        !          1528:             the one we were expecting send an RJ, otherwise ignore
        !          1529:             it.  Previously if this code got the wrong packet number
        !          1530:             it would send an RR, but that may confuse some Telebit
        !          1531:             modems and it doesn't help in any case since the receiver
        !          1532:             will probably just ignore the RR as a duplicate (that's
        !          1533:             basically what this code does).  If we totally missed the
        !          1534:             packet we will time out and send an RJ in the function
        !          1535:             fgwait_for_packet above.  */
        !          1536:          if (CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL)
        !          1537:            {
        !          1538:              /* Make sure we've acked everything up to this point.  */
        !          1539:              if (iGrecseq != iGlocal_ack)
        !          1540:                {
        !          1541:                  if (! fgsend_acks (qdaemon))
        !          1542:                    return FALSE;
        !          1543:                }
        !          1544: 
        !          1545:              /* If this is the packet we wanted, tell the sender that
        !          1546:                 it failed.  */
        !          1547:              if (CONTROL_XXX (ab[IFRAME_CONTROL]) == INEXTSEQ (iGrecseq))
        !          1548:                {
        !          1549:                  if (! fgsend_control (qdaemon, RJ, iGrecseq))
        !          1550:                    return FALSE;
        !          1551:                  cGexpect_bad_order += iGrequest_winsize - 1;
        !          1552:                }
        !          1553:            }
        !          1554: 
        !          1555:          /* We can't skip the packet data after this, because if we
        !          1556:             have lost incoming bytes the next DLE will be somewhere
        !          1557:             in what we thought was the packet data.  */
        !          1558:          iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
        !          1559:          continue;
        !          1560:        }
        !          1561: 
        !          1562:       /* We have a packet; remove the processed bytes from the receive
        !          1563:         buffer.  */
        !          1564:       iPrecstart = (iPrecstart + cwant + CFRAMELEN) % CRECBUFLEN;
        !          1565: 
        !          1566:       /* Store the control byte for the handshake routines.  */
        !          1567:       iGpacket_control = ab[IFRAME_CONTROL] & 0xff;
        !          1568: 
        !          1569:       /* Annoyingly, some UUCP packages appear to send an RR packet
        !          1570:         rather than an RJ packet when they want a packet to be
        !          1571:         resent.  If we get a duplicate RR, we treat it as an RJ.  */
        !          1572:       fduprr = FALSE;
        !          1573:       if (CONTROL_TT (ab[IFRAME_CONTROL]) == CONTROL
        !          1574:          && CONTROL_XXX (ab[IFRAME_CONTROL]) == RR
        !          1575:          && iGremote_ack == CONTROL_YYY (ab[IFRAME_CONTROL])
        !          1576:          && INEXTSEQ (iGremote_ack) != iGsendseq)
        !          1577:        {
        !          1578:          DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1579:                          "fgprocess_data: Treating duplicate RR as RJ");
        !          1580:          fduprr = TRUE;
        !          1581:        }
        !          1582: 
        !          1583:       /* Update the received sequence number from the yyy field of a
        !          1584:         data packet or an RR control packet.  If we've been delaying
        !          1585:         sending packets until we received an ack, this may send out
        !          1586:         some packets.  */
        !          1587:       if (CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL
        !          1588:          || CONTROL_XXX (ab[IFRAME_CONTROL]) == RR)
        !          1589:        {
        !          1590:          if (! fggot_ack (qdaemon, CONTROL_YYY (ab[IFRAME_CONTROL])))
        !          1591:            return FALSE;
        !          1592:        }
        !          1593: 
        !          1594:       /* If this isn't a control message, make sure we have received
        !          1595:         the expected packet sequence number, acknowledge the packet
        !          1596:         if it's the right one, and process the data.  */
        !          1597:       if (CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL)
        !          1598:        {
        !          1599:          if (CONTROL_XXX (ab[IFRAME_CONTROL]) != INEXTSEQ (iGrecseq))
        !          1600:            {
        !          1601:              /* We got the wrong packet number.  */
        !          1602:              DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1603:                              "fgprocess_data: Got packet %d; expected %d",
        !          1604:                              CONTROL_XXX (ab[IFRAME_CONTROL]),
        !          1605:                              INEXTSEQ (iGrecseq));
        !          1606: 
        !          1607:              if (cGexpect_bad_order > 0)
        !          1608:                --cGexpect_bad_order;
        !          1609:              else
        !          1610:                {
        !          1611:                  ++cGbad_order;
        !          1612:                  ++cGerror_level;
        !          1613:                  if (! fgcheck_errors (qdaemon))
        !          1614:                    return FALSE;
        !          1615:                }
        !          1616: 
        !          1617:              /* This code used to send an RR to encourage the other
        !          1618:                 side to get back in synch, but that may confuse some
        !          1619:                 Telebit modems and does little good in any case,
        !          1620:                 since the other side will probably just ignore it
        !          1621:                 anyhow (that's what this code does).  */
        !          1622:              continue;
        !          1623:            }
        !          1624: 
        !          1625:          /* We got the packet we expected.  */
        !          1626:          ++cGrec_packets;
        !          1627:          if (cGerror_level > 0
        !          1628:              && cGrec_packets % cGerror_decay == 0)
        !          1629:            --cGerror_level;
        !          1630:          cGexpect_bad_order = 0;
        !          1631: 
        !          1632:          iGrecseq = INEXTSEQ (iGrecseq);
        !          1633: 
        !          1634:          DEBUG_MESSAGE1 (DEBUG_PROTO,
        !          1635:                          "fgprocess_data: Got packet %d", iGrecseq);
        !          1636: 
        !          1637:          /* Tell the caller that we found something.  */
        !          1638:          if (pffound != NULL)
        !          1639:            *pffound = TRUE;
        !          1640: 
        !          1641:          /* If we are supposed to do acknowledgements here, send back
        !          1642:             an RR packet.  */
        !          1643:          if (fdoacks)
        !          1644:            {
        !          1645:              if (! fgsend_acks (qdaemon))
        !          1646:                return FALSE;
        !          1647:            }
        !          1648: 
        !          1649:          /* If this is a short data packet, adjust the data pointers
        !          1650:             and lengths.  */
        !          1651:          if (CONTROL_TT (ab[IFRAME_CONTROL]) == SHORTDATA)
        !          1652:            {
        !          1653:              int cshort, cmove;
        !          1654: 
        !          1655:              if ((zfirst[0] & 0x80) == 0)
        !          1656:                {
        !          1657:                  cshort = zfirst[0] & 0xff;
        !          1658:                  cmove = 1;
        !          1659:                }
        !          1660:              else
        !          1661:                {
        !          1662:                  int cbyte2;
        !          1663: 
        !          1664:                  if (cfirst > 1)
        !          1665:                    cbyte2 = zfirst[1] & 0xff;
        !          1666:                  else
        !          1667:                    cbyte2 = zsecond[0] & 0xff;
        !          1668:                  cshort = (zfirst[0] & 0x7f) + (cbyte2 << 7);
        !          1669:                  cmove = 2;
        !          1670:                }
        !          1671: 
        !          1672:              DEBUG_MESSAGE1 (DEBUG_PROTO,
        !          1673:                              "fgprocess_data: Packet short by %d",
        !          1674:                              cshort);
        !          1675: 
        !          1676:              /* Adjust the start of the buffer for the bytes used
        !          1677:                 by the count.  */
        !          1678:              if (cfirst > cmove)
        !          1679:                {
        !          1680:                  zfirst += cmove;
        !          1681:                  cfirst -= cmove;
        !          1682:                }
        !          1683:              else
        !          1684:                {
        !          1685:                  zfirst = zsecond + (cmove - cfirst);
        !          1686:                  cfirst = csecond - (cmove - cfirst);
        !          1687:                  csecond = 0;
        !          1688:                }
        !          1689: 
        !          1690:              /* Adjust the length of the buffer for the bytes we are
        !          1691:                 not supposed to consider.  */
        !          1692:              cshort -= cmove;
        !          1693:              if (csecond >= cshort)
        !          1694:                csecond -= cshort;
        !          1695:              else
        !          1696:                {
        !          1697:                  cfirst -= cshort - csecond;
        !          1698:                  csecond = 0;
        !          1699:                }
        !          1700: 
        !          1701: #if DEBUG > 0
        !          1702:              /* This should not happen, but just in case.  */
        !          1703:              if (cfirst < 0)
        !          1704:                cfirst = 0;
        !          1705: #endif
        !          1706:            }
        !          1707: 
        !          1708:          if (! fgot_data (qdaemon, zfirst, (size_t) cfirst,
        !          1709:                           zsecond, (size_t) csecond,
        !          1710:                           -1, -1, (long) -1,
        !          1711:                           INEXTSEQ (iGremote_ack) == iGsendseq,
        !          1712:                           pfexit))
        !          1713:            return FALSE;
        !          1714: 
        !          1715:          /* If fgot_data told us that we were finished, get out.  */
        !          1716:          if (*pfexit)
        !          1717:            return TRUE;
        !          1718: 
        !          1719:          /* If we've been asked to return control packets, get out
        !          1720:             now.  */
        !          1721:          if (freturncontrol)
        !          1722:            {
        !          1723:              *pfexit = TRUE;
        !          1724:              return TRUE;
        !          1725:            }
        !          1726: 
        !          1727:          continue;
        !          1728:        }
        !          1729: 
        !          1730:       /* Handle control messages here. */
        !          1731: #if DEBUG > 1
        !          1732:       if (FDEBUGGING (DEBUG_PROTO)
        !          1733:          || (FDEBUGGING (DEBUG_ABNORMAL)
        !          1734:              && CONTROL_XXX (ab[IFRAME_CONTROL]) != RR))
        !          1735:        ulog (LOG_DEBUG, "fgprocess_data: Got control %s %d",
        !          1736:              azGcontrol[CONTROL_XXX (ab[IFRAME_CONTROL])],
        !          1737:              CONTROL_YYY (ab[IFRAME_CONTROL]));
        !          1738: #endif
        !          1739: 
        !          1740:       switch (CONTROL_XXX (ab[IFRAME_CONTROL]))
        !          1741:        {
        !          1742:        case CLOSE:
        !          1743:          /* The other side has closed the connection.  */
        !          1744:          if (fLog_sighup)
        !          1745:            {
        !          1746:              ulog (LOG_ERROR, "Received unexpected CLOSE packet");
        !          1747:              (void) fgsend_control (qdaemon, CLOSE, 0);
        !          1748:            }
        !          1749:          return FALSE;
        !          1750:        case RR:
        !          1751:          /* Acknowledge receipt of a packet.  This was already handled
        !          1752:             above, unless we are treating it as RJ.  */
        !          1753:          if (! fduprr)
        !          1754:            break;
        !          1755:          /* Fall through.  */
        !          1756:        case RJ:
        !          1757:          /* The other side dropped a packet.  Begin retransmission with
        !          1758:             the packet following the one acknowledged.  We don't
        !          1759:             retransmit the packets immediately, but instead wait
        !          1760:             for the first one to be acked.  This prevents us from
        !          1761:             sending an entire window several times if we get several
        !          1762:             RJ packets.  */
        !          1763:          iGremote_ack = CONTROL_YYY (ab[IFRAME_CONTROL]);
        !          1764:          iGretransmit_seq = INEXTSEQ (iGremote_ack);
        !          1765:          if (iGretransmit_seq == iGsendseq)
        !          1766:            iGretransmit_seq = -1;
        !          1767:          else
        !          1768:            {
        !          1769:              char *zpack;
        !          1770: 
        !          1771:              DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1772:                              "fgprocess_data: Remote reject: next %d resending %d",
        !          1773:                              iGsendseq, iGretransmit_seq);
        !          1774: 
        !          1775:              ++cGresent_packets;
        !          1776:              ++cGremote_rejects;
        !          1777:              ++cGerror_level;
        !          1778:              if (! fgcheck_errors (qdaemon))
        !          1779:                return FALSE;
        !          1780:              zpack = zgadjust_ack (iGretransmit_seq);
        !          1781:              if (! fsend_data (qdaemon->qconn, zpack,
        !          1782:                                CFRAMELEN + CPACKLEN (zpack),
        !          1783:                                TRUE))
        !          1784:                return FALSE;
        !          1785:            }
        !          1786:          break;
        !          1787:        case SRJ:
        !          1788:          /* Selectively reject a particular packet.  This is not used
        !          1789:             by UUCP, but it's easy to support.  */
        !          1790:          DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !          1791:                          "fgprocess_data: Selective reject of %d",
        !          1792:                          CONTROL_YYY (ab[IFRAME_CONTROL]));
        !          1793:          {
        !          1794:            char *zpack;
        !          1795: 
        !          1796:            ++cGresent_packets;
        !          1797:            ++cGremote_rejects;
        !          1798:            ++cGerror_level;
        !          1799:            zpack = zgadjust_ack (CONTROL_YYY (ab[IFRAME_CONTROL]));
        !          1800:            if (! fsend_data (qdaemon->qconn, zpack,
        !          1801:                              CFRAMELEN + CPACKLEN (zpack),
        !          1802:                              TRUE))
        !          1803:              return FALSE;
        !          1804:          }
        !          1805:          break;
        !          1806:        case INITC:
        !          1807:        case INITB:
        !          1808:        case INITA:
        !          1809:          /* Ignore attempts to reinitialize.  */
        !          1810:          break;
        !          1811:        }
        !          1812: 
        !          1813:       /* If we've been asked to return control packets, get out.  */
        !          1814:       if (freturncontrol)
        !          1815:        {
        !          1816:          *pfexit = TRUE;
        !          1817:          return TRUE;
        !          1818:        }
        !          1819: 
        !          1820:       /* Loop around to look for the next packet, if any.  */
        !          1821:     }
        !          1822: 
        !          1823:   /* There is no data left in the receive buffer.  */
        !          1824:   if (pcneed != NULL)
        !          1825:     *pcneed = CFRAMELEN;
        !          1826:   return TRUE;
        !          1827: }
        !          1828: 
        !          1829: /* Compute the 'g' protocol checksum.  This is unfortunately rather
        !          1830:    awkward.  This is the most time consuming code in the entire
        !          1831:    program.  It's also not a great checksum, since it can be fooled
        !          1832:    by some single bit errors.  */
        !          1833: 
        !          1834: /* Sorry about this knavery, but it speeds up the VAX code
        !          1835:    significantly.  It would be better to rewrite the whole routine in
        !          1836:    assembler.  */
        !          1837: #ifdef __GNUC__
        !          1838: #ifdef __vax__
        !          1839: #define VAX_ASM 1
        !          1840: #endif
        !          1841: #endif
        !          1842: 
        !          1843: #if VAX_ASM
        !          1844: #define ROTATE(i) \
        !          1845:   asm ("cvtwl %1,%0\n\trotl $1,%0,%0" : "=g" (i) : "g" (i))
        !          1846: #else
        !          1847: #define ROTATE(i) i += i + ((i & 0x8000) >> 15)
        !          1848: #endif
        !          1849: 
        !          1850: #define ITERATION \
        !          1851:       /* Rotate ichk1 left.  */ \
        !          1852:       ROTATE (ichk1); \
        !          1853:  \
        !          1854:       /* The guts of the checksum.  */ \
        !          1855:       b = BUCHAR (*z++); \
        !          1856:       if (b != 0) \
        !          1857:        { \
        !          1858:          ichk1 &= 0xffff; \
        !          1859:          ichk1 += b; \
        !          1860:          ichk2 += ichk1 ^ c; \
        !          1861:          if ((ichk1 >> 16) != 0) \
        !          1862:            ichk1 ^= ichk2; \
        !          1863:        } \
        !          1864:       else \
        !          1865:        { \
        !          1866:          ichk2 += ichk1 ^ c; \
        !          1867:          ichk1 ^= ichk2; \
        !          1868:        } \
        !          1869:  \
        !          1870:       --c
        !          1871: 
        !          1872: static int
        !          1873: igchecksum (z, c)
        !          1874:      register const char *z;
        !          1875:      register size_t c;
        !          1876: {
        !          1877:   register unsigned long ichk1, ichk2;
        !          1878: 
        !          1879:   ichk1 = 0xffff;
        !          1880:   ichk2 = 0;
        !          1881: 
        !          1882:   do
        !          1883:     {
        !          1884:       register unsigned int b;
        !          1885: 
        !          1886:       ITERATION;
        !          1887:       ITERATION;
        !          1888:       ITERATION;
        !          1889:       ITERATION;
        !          1890:     }
        !          1891:   while (c > 0);
        !          1892: 
        !          1893:   return ichk1 & 0xffff;
        !          1894: }
        !          1895: 
        !          1896: /* We use a separate function compute the checksum if the block is
        !          1897:    split around the end of the receive buffer since it occurs much
        !          1898:    less frequently and the checksum is already high up in the
        !          1899:    profiles.  These functions are almost identical, and this one
        !          1900:    actually only has a few more instructions in the inner loop.  */
        !          1901: 
        !          1902: static int
        !          1903: igchecksum2 (zfirst, cfirst, zsecond, csecond)
        !          1904:      const char *zfirst;
        !          1905:      size_t cfirst;
        !          1906:      const char *zsecond;
        !          1907:      size_t csecond;
        !          1908: {
        !          1909:   register unsigned long ichk1, ichk2;
        !          1910:   register const char *z;
        !          1911:   register size_t c;
        !          1912: 
        !          1913:   z = zfirst;
        !          1914:   c = cfirst + csecond;
        !          1915: 
        !          1916:   ichk1 = 0xffff;
        !          1917:   ichk2 = 0;
        !          1918: 
        !          1919:   do
        !          1920:     {
        !          1921:       register unsigned int b;
        !          1922: 
        !          1923:       ITERATION;
        !          1924: 
        !          1925:       /* If the first buffer has been finished, switch to the second.  */
        !          1926:       --cfirst;
        !          1927:       if (cfirst == 0)
        !          1928:        z = zsecond;
        !          1929:     }
        !          1930:   while (c > 0);
        !          1931: 
        !          1932:   return ichk1 & 0xffff;
        !          1933: }

unix.superglobalmegacorp.com

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