|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.