1/* proti.c 2 The 'i' protocol. 3 4 Copyright (C) 1992, 1993, 1995, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char proti_rcsid[] = "$Id: proti.c,v 1.36 2002/03/05 19:10:41 ian Rel $"; 29#endif 30 31#include <ctype.h> 32#include <errno.h> 33 34#include "uudefs.h" 35#include "uuconf.h" 36#include "conn.h" 37#include "trans.h" 38#include "system.h" 39#include "prot.h" 40 41/* The 'i' protocol is a simple sliding window protocol, created by 42 me. It is in many ways similar to the 'g' protocol. Several ideas 43 are also taken from the paper ``A High-Throughput Message Transport 44 System'' by P. Lauder. I don't know where the paper was published, 45 but the author's e-mail address is piers@cs.su.oz.au. However, I 46 haven't adopted his main idea, which is to dispense with windows 47 entirely. This is because some links still do require flow control 48 and, more importantly, because I want to have a limit to the amount 49 of data I must be able to resend upon request. To reduce the costs 50 of window acknowledgements, I use a large window and only require 51 an ack at the halfway point. 52 53 Each packet starts with a header containing the following 54 information: 55 56 Intro byte 8 bits byte 1 57 Packet number 5 bits byte 2 58 Local channel 3 bits 59 Packet ack 5 bits byte 3 60 Remote channel 3 bits 61 Packet type 3 bits bytes 4-5 62 Direction 1 bit 63 Data length 12 bits 64 Header check 8 bits byte 6 65 66 If the data length is not 0, this is followed by the data and a 32 67 bit CRC checksum. 68 69 The following packet types are defined: 70 71 SYNC Initialize the connection 72 DATA Data packet 73 ACK Simple acknowledgement with no data 74 NAK Negative acknowledgement; requests resend of single packet 75 SPOS Set file position 76 CLOSE Close the connection 77 */ 78 79/* The offsets of the bytes in the packet header. */ 80 81#define IHDR_INTRO (0) 82#define IHDR_LOCAL (1) 83#define IHDR_REMOTE (2) 84#define IHDR_CONTENTS1 (3) 85#define IHDR_CONTENTS2 (4) 86#define IHDR_CHECK (5) 87 88/* Macros to set and extract values of IHDR_LOCAL and IHDR_REMOTE. */ 89#define IHDRWIN_SET(iseq, ichan) (((iseq) << 3) | (ichan)) 90#define IHDRWIN_GETSEQ(ival) (((ival) >> 3) & 0x1f) 91#define IHDRWIN_GETCHAN(ival) ((ival) & 0x07) 92 93/* Macros to set and extract values of IHDR_CONTENTS fields. */ 94#define IHDRCON_SET1(ttype, fcaller, cbytes) \ 95 (((ttype) << 5) | ((fcaller) ? (1 << 4) : 0) | (((cbytes) >> 8) & 0x0f)) 96#define IHDRCON_SET2(ttype, fcaller, cbytes) ((cbytes) & 0xff) 97#define THDRCON_GETTYPE(i1, i2) (((i1) >> 5) & 0x07) 98#define FHDRCON_GETCALLER(i1, i2) (((i1) & (1 << 4)) != 0) 99#define CHDRCON_GETBYTES(i1, i2) ((((i1) & 0x0f) << 8) | ((i2) & 0xff)) 100 101/* Macros for the IHDR_CHECK field. */ 102#define IHDRCHECK_VAL(zhdr) \ 103 ((zhdr[IHDR_LOCAL] \ 104 ^ zhdr[IHDR_REMOTE] \ 105 ^ zhdr[IHDR_CONTENTS1] \ 106 ^ zhdr[IHDR_CONTENTS2]) \ 107 & 0xff) 108 109/* Length of the packet header. */ 110#define CHDRLEN (6) 111 112/* Amount of space to skip between start of packet and actual data. 113 This is used to make the actual data longword aligned, to encourage 114 good performance when copying data into the buffer. */ 115#define CHDRSKIPLEN (CHDRLEN + (sizeof (long) - CHDRLEN % sizeof (long))) 116 117/* Amount of space to skip between memory buffer and header. */ 118#define CHDROFFSET (CHDRSKIPLEN - CHDRLEN) 119 120/* Length of the trailing checksum. */ 121#define CCKSUMLEN (4) 122 123/* Macros to set and get the checksum. These multiply evaluate their 124 arguments. */ 125#define ICKSUM_GET(z) \ 126 ((((((((unsigned long) ((z)[0] & 0xff)) << 8) \ 127 | (unsigned long) ((z)[1] & 0xff)) << 8) \ 128 | (unsigned long) ((z)[2] & 0xff)) << 8) \ 129 | (unsigned long) ((z)[3] & 0xff)) 130#define UCKSUM_SET(z, i) \ 131 (void) ((z)[0] = (((i) >> 24) & 0xff), \ 132 (z)[1] = (((i) >> 16) & 0xff), \ 133 (z)[2] = (((i) >> 8) & 0xff), \ 134 (z)[3] = ((i) & 0xff)) 135 136/* The header introduction character. */ 137#define IINTRO ('\007') 138 139/* The packet types. */ 140 141#define DATA (0) 142#define SYNC (1) 143#define ACK (2) 144#define NAK (3) 145#define SPOS (4) 146#define CLOSE (5) 147 148/* Largest possible packet size. */ 149#define IMAXPACKSIZE ((1 << 12) - 1) 150 151/* Largest possible sequence number (plus 1). */ 152#define IMAXSEQ 32 153 154/* Get the next sequence number given a sequence number. */ 155#define INEXTSEQ(i) (((i) + 1) & (IMAXSEQ - 1)) 156 157/* Get the previous sequence number given a sequence number. */ 158#define IPREVSEQ(i) (((i) + IMAXSEQ - 1) & (IMAXSEQ - 1)) 159 160/* Compute i1 - i2 in sequence space (i.e., the number of packets from 161 i2 to i1). */ 162#define CSEQDIFF(i1, i2) (((i1) + IMAXSEQ - (i2)) & (IMAXSEQ - 1)) 163 164/* Largest possible channel number (plus 1). */ 165#define IMAXICHAN (8) 166 167/* Default packet size to request (protocol parameter 168 ``packet-size''). */ 169#define IREQUEST_PACKSIZE (1024) 170 171/* Default window size to request (protocol parameter ``window''). */ 172#define IREQUEST_WINSIZE (16) 173 174/* Default timeout to use when sending the SYNC packet (protocol 175 parameter ``sync-timeout''). */ 176#define CSYNC_TIMEOUT (10) 177 178/* Default number of times to retry sending the SYNC packet (protocol 179 parameter ``sync-retries''). */ 180#define CSYNC_RETRIES (6) 181 182/* Default timeout to use when waiting for a packet (protocol 183 parameter ``timeout''). */ 184#define CTIMEOUT (10) 185 186/* Default number of times to retry sending a packet before giving up 187 (protocol parameter ``retries''). */ 188#define CRETRIES (6) 189 190/* Default maximum level of errors to accept before giving up 191 (protocol parameter ``errors''). */ 192#define CERRORS (100) 193 194/* Default decay rate. Each time we receive this many packets 195 succesfully, we decrement the error level by one (protocol 196 parameter ``error-decay''). */ 197#define CERROR_DECAY (10) 198 199/* The default list of characters to avoid: XON and XOFF. This string 200 is processed as an escape sequence. This is 'j' protocol parameter 201 ``avoid''; it is defined in this file because the 'i' and 'j' 202 protocols share protocol parameters. */ 203#define ZAVOID "\\021\\023" 204 205/* Local variables. */ 206 207/* Packet size to request (protocol parameter ``packet-size''). */ 208static int iIrequest_packsize = IREQUEST_PACKSIZE; 209 210/* Window size to request (protocol parameter ``window''). */ 211static int iIrequest_winsize = IREQUEST_WINSIZE; 212 213/* Remote packet size (set from SYNC packet or from 214 iIforced_remote_packsize). */ 215static int iIremote_packsize; 216 217/* Size which buffers were allocated for. */ 218static int iIalc_packsize; 219 220/* Forced remote packet size, used if non-zero (protocol parameter 221 ``remote-packet-size''). There is no forced remote window size 222 because the ACK strategy requires that both sides agree on the 223 window size. */ 224static int iIforced_remote_packsize = 0; 225 226/* Remote window size (set from SYNC packet). */ 227static int iIremote_winsize; 228 229/* Timeout to use when sending the SYNC packet (protocol 230 parameter ``sync-timeout''). */ 231int cIsync_timeout = CSYNC_TIMEOUT; 232 233/* Number of times to retry sending the SYNC packet (protocol 234 parameter ``sync-retries''). */ 235static int cIsync_retries = CSYNC_RETRIES; 236 237/* Timeout to use when waiting for a packet (protocol parameter 238 ``timeout''). */ 239static int cItimeout = CTIMEOUT; 240 241/* Timeout to use when waiting for an acknowledgement to open up space 242 in the window. This is computed based on the window size and the 243 connection speed. */ 244static int cIwindow_timeout = CTIMEOUT; 245 246/* Number of times to retry sending a packet before giving up 247 (protocol parameter ``retries''). */ 248static int cIretries = CRETRIES; 249 250/* Maximum level of errors to accept before giving up (protocol 251 parameter ``errors''). */ 252static int cIerrors = CERRORS; 253 254/* Each time we receive this many packets succesfully, we decrement 255 the error level by one (protocol parameter ``error-decay''). */ 256static int cIerror_decay = CERROR_DECAY; 257 258/* The number of packets we should wait to receive before sending an 259 ACK; this is set by default to half the window size we have 260 requested (protocol parameter ``ack-frequency''). */ 261static int cIack_frequency = 0; 262 263/* The set of characters to avoid (protocol parameter ``avoid''). 264 This is actually part of the 'j' protocol; it is defined in this 265 file because the 'i' and 'j' protocols use the same protocol 266 parameters. */ 267const char *zJavoid_parameter = ZAVOID; 268 269/* Routine to use when sending data. This is a hook for the 'j' 270 protocol. */ 271static boolean (*pfIsend) P((struct sconnection *qconn, const char *zsend, 272 size_t csend, boolean fdoread)); 273 274/* Routine to use to use when reading data. This is a hook for the 275 'j' protocol. */ 276static boolean (*pfIreceive) P((struct sconnection *qconn, size_t cneed, 277 size_t *pcrec, int ctimeout, 278 boolean freport)); 279 280/* Next sequence number to send. */ 281static int iIsendseq; 282 283/* Last sequence number received. */ 284static int iIrecseq; 285 286/* Last sequence number we have acknowledged. */ 287static int iIlocal_ack; 288 289/* Last sequence number remote system has acknowledged. */ 290static int iIremote_ack; 291 292/* File position we are sending from. */ 293static long iIsendpos; 294 295/* File position we are receiving to. */ 296static long iIrecpos; 297 298/* TRUE if closing the connection. */ 299static boolean fIclosing; 300 301/* Array of sent packets indexed by packet number. */ 302static char *azIsendbuffers[IMAXSEQ]; 303 304/* Array of received packets that we aren't ready to process yet, 305 indexed by packet number. */ 306static char *azIrecbuffers[IMAXSEQ]; 307 308/* For each packet sequence number, record whether we sent a NAK for 309 the packet. */ 310static boolean afInaked[IMAXSEQ]; 311 312/* Number of SYNC packets received (used only to detect whether one 313 was received). */ 314static int cIsyncs; 315 316/* Number of packets sent. */ 317static long cIsent_packets; 318 319/* Number of packets received. */ 320static long cIreceived_packets; 321 322/* Number of packets resent. */ 323static long cIresent_packets; 324 325/* Number of bad packet headers received. */ 326static long cIbad_hdr; 327 328/* Number of out of order packets received. */ 329static long cIbad_order; 330 331/* Number of bad checksums received. */ 332static long cIbad_cksum; 333 334/* Number of packets rejected by remote system. */ 335static long cIremote_rejects; 336 337/* Protocol parameter commands. */ 338 339struct uuconf_cmdtab asIproto_params[] = 340{ 341 { "packet-size", UUCONF_CMDTABTYPE_INT, (pointer) &iIrequest_packsize, 342 NULL }, 343 { "window", UUCONF_CMDTABTYPE_INT, (pointer) &iIrequest_winsize, NULL }, 344 { "remote-packet-size", UUCONF_CMDTABTYPE_INT, 345 (pointer) &iIforced_remote_packsize, NULL }, 346 { "sync-timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cIsync_timeout, 347 NULL }, 348 { "sync-retries", UUCONF_CMDTABTYPE_INT, (pointer) &cIsync_retries, 349 NULL }, 350 { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cItimeout, NULL }, 351 { "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cIretries, NULL }, 352 { "errors", UUCONF_CMDTABTYPE_INT, (pointer) &cIerrors, NULL }, 353 { "error-decay", UUCONF_CMDTABTYPE_INT, (pointer) &cIerror_decay, NULL }, 354 { "ack-frequency", UUCONF_CMDTABTYPE_INT, (pointer) &cIack_frequency, NULL }, 355 /* The ``avoid'' protocol parameter is part of the 'j' protocol, but 356 it is convenient for the 'i' and 'j' protocols to share the same 357 protocol parameter table. */ 358 { "avoid", UUCONF_CMDTABTYPE_STRING, (pointer) &zJavoid_parameter, NULL }, 359 { NULL, 0, NULL, NULL } 360}; 361 362/* Local functions. */ 363 364static boolean finak P((struct sdaemon *qdaemon, int iseq)); 365static boolean firesend P((struct sdaemon *qdaemon)); 366static boolean fiwindow_wait P((struct sdaemon *qdaemon)); 367static boolean fiwait_for_packet P((struct sdaemon *qdaemon, 368 int ctimeout, int cretries, 369 boolean fone, boolean *ftimedout)); 370static boolean ficheck_errors P((struct sdaemon *qdaemon)); 371static boolean fiprocess_data P((struct sdaemon *qdaemon, 372 boolean *pfexit, boolean *pffound, 373 size_t *pcneed)); 374static boolean fiprocess_packet P((struct sdaemon *qdaemon, 375 const char *zhdr, 376 const char *zfirst, int cfirst, 377 const char *zsecond, int csecond, 378 boolean *pfexit)); 379 380/* The 'i' protocol start routine. The work is done in a routine 381 which is also called by the 'j' protocol start routine. */ 382 383boolean 384fistart (qdaemon, pzlog) 385 struct sdaemon *qdaemon; 386 char **pzlog; 387{ 388 return fijstart (qdaemon, pzlog, IMAXPACKSIZE, fsend_data, freceive_data); 389} 390 391/* Start the protocol. This routine is called by both the 'i' and 'j' 392 protocol start routines. We keep transmitting a SYNC packet 393 containing the window and packet size we would like to receive 394 until we receive a SYNC packet from the remote system. The first 395 two bytes of the data contents of a SYNC packet are the maximum 396 packet size we want to receive (high byte, low byte), and the next 397 byte is the maximum window size we want to use. */ 398 399boolean 400fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive) 401 struct sdaemon *qdaemon; 402 char **pzlog; 403 int imaxpacksize; 404 boolean (*pfsend) P((struct sconnection *qconn, const char *zsend, 405 size_t csend, boolean fdoread)); 406 boolean (*pfreceive) P((struct sconnection *qconn, size_t cneed, 407 size_t *pcrec, int ctimeout, boolean freport)); 408{ 409 char ab[CHDRLEN + 4 + CCKSUMLEN]; 410 unsigned long icksum; 411 int ctries; 412 int csyncs; 413 long ibaud; 414 415 *pzlog = NULL; 416 417 pfIsend = pfsend; 418 pfIreceive = pfreceive; 419 420 if (iIforced_remote_packsize <= 0 421 || iIforced_remote_packsize > imaxpacksize) 422 iIforced_remote_packsize = 0; 423 else 424 iIremote_packsize = iIforced_remote_packsize; 425 iIalc_packsize = 0; 426 427 iIsendseq = 1; 428 iIrecseq = 0; 429 iIlocal_ack = 0; 430 iIremote_ack = 0; 431 iIsendpos = 0; 432 iIrecpos = 0; 433 fIclosing = FALSE; 434 435 cIsent_packets = 0; 436 cIreceived_packets = 0; 437 cIresent_packets = 0; 438 cIbad_hdr = 0; 439 cIbad_order = 0; 440 cIbad_cksum = 0; 441 cIremote_rejects = 0; 442 443 if (iIrequest_packsize < 0 || iIrequest_packsize > imaxpacksize) 444 { 445 ulog (LOG_ERROR, "Illegal protocol '%c' packet size; using %d", 446 qdaemon->qproto->bname, imaxpacksize); 447 iIrequest_packsize = imaxpacksize; 448 } 449 450 /* The maximum permissible window size is 16. Otherwise the 451 protocol can get confused because a duplicated packet may arrive 452 out of order. If the window size is large in such a case, the 453 duplicate packet may be treated as a packet in the upcoming 454 window, causing the protocol to assume that all intermediate 455 packets have been lost, leading to immense confusion. */ 456 if (iIrequest_winsize < 0 || iIrequest_winsize > IMAXSEQ / 2) 457 { 458 ulog (LOG_ERROR, "Illegal protocol '%c' window size; using %d", 459 qdaemon->qproto->bname, IREQUEST_WINSIZE); 460 iIrequest_winsize = IREQUEST_WINSIZE; 461 } 462 463 /* The default for the ACK frequency is half the window size. */ 464 if (cIack_frequency <= 0 || cIack_frequency >= iIrequest_winsize) 465 cIack_frequency = iIrequest_winsize / 2; 466 467 ab[IHDR_INTRO] = IINTRO; 468 ab[IHDR_LOCAL] = ab[IHDR_REMOTE] = IHDRWIN_SET (0, 0); 469 ab[IHDR_CONTENTS1] = IHDRCON_SET1 (SYNC, qdaemon->fcaller, 4); 470 ab[IHDR_CONTENTS2] = IHDRCON_SET2 (SYNC, qdaemon->fcaller, 4); 471 ab[IHDR_CHECK] = IHDRCHECK_VAL (ab); 472 ab[CHDRLEN + 0] = (iIrequest_packsize >> 8) & 0xff; 473 ab[CHDRLEN + 1] = iIrequest_packsize & 0xff; 474 ab[CHDRLEN + 2] = iIrequest_winsize; 475 ab[CHDRLEN + 3] = qdaemon->cchans; 476 icksum = icrc (ab + CHDRLEN, 4, ICRCINIT); 477 UCKSUM_SET (ab + CHDRLEN + 4, icksum); 478 479 /* The static cIsyncs is incremented each time a SYNC packet is 480 received. */ 481 csyncs = cIsyncs; 482 ctries = 0; 483 484 while (TRUE) 485 { 486 boolean ftimedout; 487 488 DEBUG_MESSAGE3 (DEBUG_PROTO, 489 "fistart: Sending SYNC packsize %d winsize %d channels %d", 490 iIrequest_packsize, iIrequest_winsize, qdaemon->cchans); 491 492 if (! (*pfIsend) (qdaemon->qconn, ab, CHDRLEN + 4 + CCKSUMLEN, 493 TRUE)) 494 return FALSE; 495 496 if (fiwait_for_packet (qdaemon, cIsync_timeout, 0, FALSE, 497 &ftimedout)) 498 { 499 if (csyncs != cIsyncs) 500 break; 501 } 502 else 503 { 504 if (! ftimedout) 505 return FALSE; 506 507 ++ctries; 508 if (ctries > cIsync_retries) 509 { 510 ulog (LOG_ERROR, "Protocol startup failed"); 511 return FALSE; 512 } 513 } 514 } 515 516 /* Calculate the window timeout. */ 517 ibaud = iconn_baud (qdaemon->qconn); 518 if (ibaud == 0) 519 cIwindow_timeout = cItimeout; 520 else 521 { 522 /* We expect to receive an ACK about halfway through each 523 window. In principle, an entire window might be sitting in a 524 modem buffer while we are waiting for an ACK. Therefore, the 525 minimum time we should wait for an ACK is 526 (1/2 window size) * (seconds / byte) + (roundtrip time) == 527 (1/2 window size) * (1 / (baud / 10)) + (roundtrip time) == 528 (1/2 window size) * (10 / baud) + (roundtrip time) == 529 (5 * (window size)) / baud + (roundtrip time) 530 531 The window size is iIremote_packsize * iIremote_winsize. For 532 typical settings of packsize == 1024, winsize == 16, baud == 533 9600, this equation works out to 534 (5 * 1024 * 16) / 9600 == 8 seconds 535 We then take cItimeout as the round trip time, which gives us 536 some flexibility. We get more flexibility because it is 537 quite likely that by the time we have finished sending out 538 the last packet in a window, the first one has already been 539 received by the remote system. */ 540 cIwindow_timeout = ((5 * iIremote_packsize * iIremote_winsize) / ibaud 541 + cItimeout); 542 } 543 544 /* If we are the callee, bump both timeouts by one, to make it less 545 likely that both systems will timeout simultaneously. */ 546 if (! qdaemon->fcaller) 547 { 548 ++cItimeout; 549 ++cIwindow_timeout; 550 } 551 552 /* We got a SYNC packet; set up packet buffers to use. */ 553 if (iIremote_packsize > imaxpacksize) 554 iIremote_packsize = imaxpacksize; 555 do 556 { 557 int iseq; 558 559 for (iseq = 0; iseq < IMAXSEQ; iseq++) 560 { 561 azIrecbuffers[iseq] = NULL; 562 afInaked[iseq] = FALSE; 563 azIsendbuffers[iseq] = (char *) malloc (iIremote_packsize 564 + CHDRSKIPLEN 565 + CCKSUMLEN); 566 if (azIsendbuffers[iseq] == NULL) 567 { 568 int ifree; 569 570 for (ifree = 0; ifree < iseq; ifree++) 571 free ((pointer) azIsendbuffers[ifree]); 572 break; 573 } 574 } 575 576 if (iseq >= IMAXSEQ) 577 { 578 *pzlog = 579 zbufalc (sizeof "protocol '' sending packet/window / receiving /" 580 + 64); 581 sprintf (*pzlog, 582 "protocol '%c' sending packet/window %d/%d receiving %d/%d", 583 qdaemon->qproto->bname, (int) iIremote_packsize, 584 (int) iIremote_winsize, (int) iIrequest_packsize, 585 (int) iIrequest_winsize); 586 587 iIalc_packsize = iIremote_packsize; 588 589 return TRUE; 590 } 591 592 iIremote_packsize >>= 1; 593 } 594 while (iIremote_packsize > 200); 595 596 ulog (LOG_ERROR, 597 "'%c' protocol startup failed; insufficient memory for packets", 598 qdaemon->qproto->bname); 599 600 return FALSE; 601} 602 603/* Shut down the protocol. We can be fairly informal about this, 604 since we know that the upper level protocol has already exchanged 605 hangup messages. If we didn't know that, we would have to make 606 sure that all packets before the CLOSE had been received. */ 607 608boolean 609fishutdown (qdaemon) 610 struct sdaemon *qdaemon; 611{ 612 char *z; 613 size_t clen; 614 615 fIclosing = TRUE; 616 617 z = zigetspace (qdaemon, &clen) - CHDRLEN; 618 619 z[IHDR_INTRO] = IINTRO; 620 z[IHDR_LOCAL] = IHDRWIN_SET (iIsendseq, 0); 621 z[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 622 iIlocal_ack = iIrecseq; 623 z[IHDR_CONTENTS1] = IHDRCON_SET1 (CLOSE, qdaemon->fcaller, 0); 624 z[IHDR_CONTENTS2] = IHDRCON_SET2 (CLOSE, qdaemon->fcaller, 0); 625 z[IHDR_CHECK] = IHDRCHECK_VAL (z); 626 627 DEBUG_MESSAGE0 (DEBUG_PROTO, "fishutdown: Sending CLOSE"); 628 629 if (! (*pfIsend) (qdaemon->qconn, z, CHDRLEN, FALSE)) 630 return FALSE; 631 632 ulog (LOG_NORMAL, 633 "Protocol '%c' packets: sent %ld, resent %ld, received %ld", 634 qdaemon->qproto->bname, cIsent_packets, cIresent_packets, 635 cIreceived_packets); 636 if (cIbad_hdr != 0 637 || cIbad_cksum != 0 638 || cIbad_order != 0 639 || cIremote_rejects != 0) 640 ulog (LOG_NORMAL, 641 "Errors: header %ld, checksum %ld, order %ld, remote rejects %ld", 642 cIbad_hdr, cIbad_cksum, cIbad_order, cIremote_rejects); 643 644 /* Reset the protocol parameters to their default values. */ 645 iIrequest_packsize = IREQUEST_PACKSIZE; 646 iIrequest_winsize = IREQUEST_WINSIZE; 647 iIforced_remote_packsize = 0; 648 cIsync_timeout = CSYNC_TIMEOUT; 649 cIsync_retries = CSYNC_RETRIES; 650 cItimeout = CTIMEOUT; 651 cIwindow_timeout = CTIMEOUT; 652 cIretries = CRETRIES; 653 cIerrors = CERRORS; 654 cIerror_decay = CERROR_DECAY; 655 cIack_frequency = 0; 656 zJavoid_parameter = ZAVOID; 657 658 return TRUE; 659} 660 661/* Send a command string. These are just sent as normal packets, 662 ending in a packet containing a null byte. */ 663 664boolean 665fisendcmd (qdaemon, z, ilocal, iremote) 666 struct sdaemon *qdaemon; 667 const char *z; 668 int ilocal; 669 int iremote; 670{ 671 size_t clen; 672 673 DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "fisendcmd: Sending command \"%s\"", z); 674 675 clen = strlen (z); 676 677 while (TRUE) 678 { 679 char *zpacket; 680 size_t csize; 681 682 zpacket = zigetspace (qdaemon, &csize); 683 684 if (clen < csize) 685 { 686 memcpy (zpacket, z, clen + 1); 687 return fisenddata (qdaemon, zpacket, clen + 1, ilocal, iremote, 688 (long) -1); 689 } 690 691 memcpy (zpacket, z, csize); 692 z += csize; 693 clen -= csize; 694 695 if (! fisenddata (qdaemon, zpacket, csize, ilocal, iremote, (long) -1)) 696 return FALSE; 697 } 698 /*NOTREACHED*/ 699} 700 701/* Send a NAK. */ 702 703static boolean 704finak (qdaemon, iseq) 705 struct sdaemon *qdaemon; 706 int iseq; 707{ 708 char abnak[CHDRLEN]; 709 710 abnak[IHDR_INTRO] = IINTRO; 711 abnak[IHDR_LOCAL] = IHDRWIN_SET (iseq, 0); 712 abnak[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 713 iIlocal_ack = iIrecseq; 714 abnak[IHDR_CONTENTS1] = IHDRCON_SET1 (NAK, qdaemon->fcaller, 0); 715 abnak[IHDR_CONTENTS2] = IHDRCON_SET2 (NAK, qdaemon->fcaller, 0); 716 abnak[IHDR_CHECK] = IHDRCHECK_VAL (abnak); 717 718 afInaked[iseq] = TRUE; 719 720 DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL, 721 "finak: Sending NAK %d", iseq); 722 723 return (*pfIsend) (qdaemon->qconn, abnak, CHDRLEN, TRUE); 724} 725 726/* Resend the latest packet the remote has not acknowledged. */ 727 728static boolean 729firesend (qdaemon) 730 struct sdaemon *qdaemon; 731{ 732 int iseq; 733 char *zhdr; 734 size_t clen; 735 736 iseq = INEXTSEQ (iIremote_ack); 737 if (iseq == iIsendseq) 738 { 739 /* Everything has been ACKed and there is nothing to resend. */ 740 return TRUE; 741 } 742 743 DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL, 744 "firesend: Resending packet %d", iseq); 745 746 /* Update the received sequence number. */ 747 zhdr = azIsendbuffers[iseq] + CHDROFFSET; 748 if (IHDRWIN_GETSEQ (zhdr[IHDR_REMOTE]) != iIrecseq) 749 { 750 int iremote; 751 752 iremote = IHDRWIN_GETCHAN (zhdr[IHDR_REMOTE]); 753 zhdr[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, iremote); 754 zhdr[IHDR_CHECK] = IHDRCHECK_VAL (zhdr); 755 iIlocal_ack = iIrecseq; 756 } 757 758 ++cIresent_packets; 759 760 clen = CHDRCON_GETBYTES (zhdr[IHDR_CONTENTS1], 761 zhdr[IHDR_CONTENTS2]); 762 763 return (*pfIsend) (qdaemon->qconn, zhdr, 764 CHDRLEN + clen + (clen > 0 ? CCKSUMLEN : 0), 765 TRUE); 766} 767 768/* Wait until there is an opening in the receive window of the remote 769 system. */ 770 771static boolean 772fiwindow_wait (qdaemon) 773 struct sdaemon *qdaemon; 774{ 775 /* iIsendseq is the sequence number we are sending, and iIremote_ack 776 is the last sequence number acknowledged by the remote. */ 777 while (CSEQDIFF (iIsendseq, iIremote_ack) > iIremote_winsize) 778 { 779 /* If a NAK is lost, it is possible for the other side to be 780 sending a stream of packets while we are waiting for an ACK. 781 This should be caught in fiprocess_data; if it is about to 782 send an ACK, but it has an unacknowledged packet to send, it 783 sends the entire packet. Hopefully that will trigger an ACK 784 or a NAK and get us going again. */ 785 DEBUG_MESSAGE0 (DEBUG_PROTO, "fiwindow_wait: Waiting for ACK"); 786 if (! fiwait_for_packet (qdaemon, cIwindow_timeout, cIretries, 787 TRUE, (boolean *) NULL)) 788 return FALSE; 789 } 790 791 return TRUE; 792} 793 794/* Get buffer space to use for packet data. We return a pointer to 795 the space to be used for the actual data, leaving room for the 796 header. */ 797 798/*ARGSUSED*/ 799char * 800zigetspace (qdaemon, pclen) 801 struct sdaemon *qdaemon ATTRIBUTE_UNUSED; 802 size_t *pclen; 803{ 804 *pclen = iIremote_packsize; 805 return azIsendbuffers[iIsendseq] + CHDRSKIPLEN; 806} 807 808/* Send a data packet. The zdata argument will always point to value 809 returned by zigetspace, so we know that we have room before it for 810 the header information. */ 811 812boolean 813fisenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos) 814 struct sdaemon *qdaemon; 815 char *zdata; 816 size_t cdata; 817 int ilocal; 818 int iremote; 819 long ipos; 820{ 821 char *zhdr; 822 unsigned long icksum; 823 boolean fret; 824 825#if DEBUG > 0 826 if (ilocal < 0 || ilocal >= IMAXICHAN 827 || iremote < 0 || iremote >= IMAXICHAN) 828 ulog (LOG_FATAL, "fisenddata: ilocal %d iremote %d", ilocal, iremote); 829#endif 830 831 /* If we are changing the file position, we must send an SPOS 832 packet. */ 833 if (ipos != iIsendpos && ipos != (long) -1) 834 { 835 int inext; 836 char *zspos; 837 838 /* We need to get a buffer to hold the SPOS packet, and it needs 839 to be next sequence number. However, the data we have been 840 given is currently in the next sequence number buffer. So we 841 shuffle the buffers around. */ 842 inext = INEXTSEQ (iIsendseq); 843 zspos = azIsendbuffers[inext]; 844 azIsendbuffers[inext] = zdata - CHDRSKIPLEN; 845 azIsendbuffers[iIsendseq] = zspos; 846 zspos += CHDROFFSET; 847 848 zspos[IHDR_INTRO] = IINTRO; 849 zspos[IHDR_LOCAL] = IHDRWIN_SET (iIsendseq, 0); 850 zspos[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 851 iIlocal_ack = iIrecseq; 852 zspos[IHDR_CONTENTS1] = IHDRCON_SET1 (SPOS, qdaemon->fcaller, 853 CCKSUMLEN); 854 zspos[IHDR_CONTENTS2] = IHDRCON_SET2 (SPOS, qdaemon->fcaller, 855 CCKSUMLEN); 856 zspos[IHDR_CHECK] = IHDRCHECK_VAL (zspos); 857 UCKSUM_SET (zspos + CHDRLEN, (unsigned long) ipos); 858 icksum = icrc (zspos + CHDRLEN, CCKSUMLEN, ICRCINIT); 859 UCKSUM_SET (zspos + CHDRLEN + CCKSUMLEN, icksum); 860 861 /* Wait for an opening in the window. */ 862 if (iIremote_winsize > 0 863 && CSEQDIFF (iIsendseq, iIremote_ack) > iIremote_winsize) 864 { 865 if (! fiwindow_wait (qdaemon)) 866 return FALSE; 867 } 868 869 DEBUG_MESSAGE1 (DEBUG_PROTO, "fisenddata: Sending SPOS %ld", 870 ipos); 871 872 if (! (*pfIsend) (qdaemon->qconn, zspos, 873 CHDRLEN + CCKSUMLEN + CCKSUMLEN, TRUE)) 874 return FALSE; 875 876 iIsendseq = INEXTSEQ (iIsendseq); 877 iIsendpos = ipos; 878 } 879 880 zhdr = zdata - CHDRLEN; 881 zhdr[IHDR_INTRO] = IINTRO; 882 zhdr[IHDR_LOCAL] = IHDRWIN_SET (iIsendseq, ilocal); 883 zhdr[IHDR_CONTENTS1] = IHDRCON_SET1 (DATA, qdaemon->fcaller, cdata); 884 zhdr[IHDR_CONTENTS2] = IHDRCON_SET2 (DATA, qdaemon->fcaller, cdata); 885 886 /* Compute and set the checksum. */ 887 if (cdata > 0) 888 { 889 icksum = icrc (zdata, cdata, ICRCINIT); 890 UCKSUM_SET (zdata + cdata, icksum); 891 } 892 893 /* Wait until there is an opening in the window (we hope to not have 894 to wait here at all, actually; ideally the window should be large 895 enough to avoid a wait). */ 896 if (iIremote_winsize > 0 897 && CSEQDIFF (iIsendseq, iIremote_ack) > iIremote_winsize) 898 { 899 if (! fiwindow_wait (qdaemon)) 900 return FALSE; 901 } 902 903 /* We only fill in IHDR_REMOTE now, since only now do know the 904 correct value of iIrecseq. */ 905 zhdr[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, iremote); 906 iIlocal_ack = iIrecseq; 907 zhdr[IHDR_CHECK] = IHDRCHECK_VAL (zhdr); 908 909 DEBUG_MESSAGE4 (DEBUG_PROTO, 910 "fisenddata: Sending packet %d size %d local %d remote %d", 911 iIsendseq, (int) cdata, ilocal, iremote); 912 913 iIsendseq = INEXTSEQ (iIsendseq); 914 ++cIsent_packets; 915 916 fret = (*pfIsend) (qdaemon->qconn, zhdr, 917 cdata + CHDRLEN + (cdata > 0 ? CCKSUMLEN : 0), 918 TRUE); 919 920 iIsendpos += cdata; 921 922 if (fret && iPrecstart != iPrecend) 923 { 924 boolean fexit; 925 926 fret = fiprocess_data (qdaemon, &fexit, (boolean *) NULL, 927 (size_t *) NULL); 928 } 929 930 return fret; 931} 932 933/* Wait for data to come in. */ 934 935boolean 936fiwait (qdaemon) 937 struct sdaemon *qdaemon; 938{ 939 return fiwait_for_packet (qdaemon, cItimeout, cIretries, 940 FALSE, (boolean *) NULL); 941} 942 943/* Wait for a packet. Either there is no data to send, or the remote 944 window is full. */ 945 946static boolean 947fiwait_for_packet (qdaemon, ctimeout, cretries, fone, pftimedout) 948 struct sdaemon *qdaemon; 949 int ctimeout; 950 int cretries; 951 boolean fone; 952 boolean *pftimedout; 953{ 954 int cshort; 955 int ctimeouts; 956 957 if (pftimedout != NULL) 958 *pftimedout = FALSE; 959 960 cshort = 0; 961 ctimeouts = 0; 962 963 while (TRUE) 964 { 965 boolean fexit, ffound; 966 size_t cneed; 967 size_t crec; 968 969 if (! fiprocess_data (qdaemon, &fexit, &ffound, &cneed)) 970 return FALSE; 971 972 if (fexit || (fone && ffound)) 973 return TRUE; 974 975 if (cneed == 0) 976 continue; 977 978 DEBUG_MESSAGE1 (DEBUG_PROTO, "fiwait_for_packet: Need %d bytes", 979 (int) cneed); 980 981 if (! (*pfIreceive) (qdaemon->qconn, cneed, &crec, ctimeout, TRUE)) 982 return FALSE; 983 984 if (crec != 0) 985 { 986 /* If we didn't get enough data twice in a row, we may have 987 dropped some data and be waiting for the end of a large 988 packet. Incrementing iPrecstart will force 989 fiprocess_data to skip the current packet and try to find 990 the next one. */ 991 if (crec >= cneed) 992 cshort = 0; 993 else 994 { 995 ++cshort; 996 if (cshort > 1) 997 { 998 iPrecstart = (iPrecstart + 1) % CRECBUFLEN; 999 cshort = 0; 1000 } 1001 } 1002 } 1003 else 1004 { 1005 int i; 1006 1007 /* We timed out on the read. */ 1008 ++ctimeouts; 1009 if (ctimeouts > cretries) 1010 { 1011 if (cretries > 0) 1012 ulog (LOG_ERROR, "Timed out waiting for packet"); 1013 if (pftimedout != NULL) 1014 *pftimedout = TRUE; 1015 return FALSE; 1016 } 1017 1018 /* Clear out the list of packets we have sent NAKs for. We 1019 should have seen some sort of response by now. */ 1020 for (i = 0; i < IMAXSEQ; i++) 1021 afInaked[i] = FALSE; 1022 1023 /* Send a NAK for the packet we want, and, if we have an 1024 unacknowledged packet, send it again. */ 1025 if (! finak (qdaemon, INEXTSEQ (iIrecseq)) 1026 || ! firesend (qdaemon)) 1027 return FALSE; 1028 } 1029 } 1030 /*NOTREACHED*/ 1031} 1032 1033/* Make sure we haven't overflowed the permissible error level. */ 1034 1035static boolean 1036ficheck_errors (qdaemon) 1037 struct sdaemon *qdaemon; 1038{ 1039 if (cIerrors < 0) 1040 return TRUE; 1041 1042 if (((cIbad_order + cIbad_hdr + cIbad_cksum + cIremote_rejects) 1043 - (cIreceived_packets / cIerror_decay)) 1044 > cIerrors) 1045 { 1046 /* Try shrinking the packet size. */ 1047 if (iIrequest_packsize > 400) 1048 { 1049 char absync[CHDRLEN + 3 + CCKSUMLEN]; 1050 unsigned long icksum; 1051 1052 /* Don't bother sending the number of channels in this 1053 packet. */ 1054 iIrequest_packsize /= 2; 1055 absync[IHDR_INTRO] = IINTRO; 1056 absync[IHDR_LOCAL] = IHDRWIN_SET (0, 0); 1057 absync[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 1058 iIlocal_ack = iIrecseq; 1059 absync[IHDR_CONTENTS1] = IHDRCON_SET1 (SYNC, qdaemon->fcaller, 3); 1060 absync[IHDR_CONTENTS2] = IHDRCON_SET2 (SYNC, qdaemon->fcaller, 3); 1061 absync[IHDR_CHECK] = IHDRCHECK_VAL (absync); 1062 absync[CHDRLEN + 0] = (iIrequest_packsize >> 8) & 0xff; 1063 absync[CHDRLEN + 1] = iIrequest_packsize & 0xff; 1064 absync[CHDRLEN + 2] = iIrequest_winsize; 1065 icksum = icrc (absync + CHDRLEN, 3, ICRCINIT); 1066 UCKSUM_SET (absync + CHDRLEN + 3, icksum); 1067 1068 cIerrors *= 2; 1069 1070 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1071 "ficheck_errors: Sending SYNC packsize %d winsize %d", 1072 iIrequest_packsize, iIrequest_winsize); 1073 1074 return (*pfIsend) (qdaemon->qconn, absync, 1075 CHDRLEN + 3 + CCKSUMLEN, TRUE); 1076 } 1077 1078 ulog (LOG_ERROR, "Too many '%c' protocol errors", 1079 qdaemon->qproto->bname); 1080 return FALSE; 1081 } 1082 1083 return TRUE; 1084} 1085 1086/* Process data waiting in the receive buffer, passing to the 1087 fgot_data function. */ 1088 1089static boolean 1090fiprocess_data (qdaemon, pfexit, pffound, pcneed) 1091 struct sdaemon *qdaemon; 1092 boolean *pfexit; 1093 boolean *pffound; 1094 size_t *pcneed; 1095{ 1096 boolean fbadhdr; 1097 1098 if (pfexit != NULL) 1099 *pfexit = FALSE; 1100 if (pffound != NULL) 1101 *pffound = FALSE; 1102 1103 fbadhdr = FALSE; 1104 1105 while (iPrecstart != iPrecend) 1106 { 1107 char ab[CHDRLEN]; 1108 int cfirst, csecond; 1109 char *zfirst, *zsecond; 1110 int i; 1111 int iget; 1112 int ttype; 1113 int iseq; 1114 int csize; 1115 int iack; 1116 1117 /* If we're closing the connection, ignore any data remaining in 1118 the input buffer. */ 1119 if (fIclosing) 1120 { 1121 if (pfexit != NULL) 1122 *pfexit = TRUE; 1123 if (pcneed != NULL) 1124 *pcneed = 0; 1125 return TRUE; 1126 } 1127 1128 /* Look for the IINTRO character. */ 1129 if (abPrecbuf[iPrecstart] != IINTRO) 1130 { 1131 char *zintro; 1132 int cintro; 1133 1134 cintro = iPrecend - iPrecstart; 1135 if (cintro < 0) 1136 cintro = CRECBUFLEN - iPrecstart; 1137 1138 zintro = memchr (abPrecbuf + iPrecstart, IINTRO, (size_t) cintro); 1139 1140 if (zintro == NULL) 1141 { 1142 iPrecstart = (iPrecstart + cintro) % CRECBUFLEN; 1143 continue; 1144 } 1145 1146 /* We don't need % CRECBUFLEN here because zintro - (abPrecbuf 1147 + iPrecstart) < cintro <= CRECBUFLEN - iPrecstart. */ 1148 iPrecstart += zintro - (abPrecbuf + iPrecstart); 1149 } 1150 1151 /* Get the header into ab. */ 1152 for (i = 0, iget = iPrecstart; 1153 i < CHDRLEN && iget != iPrecend; 1154 i++, iget = (iget + 1) % CRECBUFLEN) 1155 ab[i] = abPrecbuf[iget]; 1156 1157 if (i < CHDRLEN) 1158 { 1159 if (pcneed != NULL) 1160 *pcneed = CHDRLEN - i; 1161 return TRUE; 1162 } 1163 1164 if ((ab[IHDR_CHECK] & 0xff) != IHDRCHECK_VAL (ab) 1165 || (FHDRCON_GETCALLER (ab[IHDR_CONTENTS1], ab[IHDR_CONTENTS2]) 1166 ? qdaemon->fcaller : ! qdaemon->fcaller)) 1167 { 1168 /* We only report a single bad header message per call, to 1169 avoid generating many errors if we get many INTRO bytes 1170 in a row. */ 1171 if (! fbadhdr) 1172 { 1173 DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL, 1174 "fiprocess_data: Bad header"); 1175 1176 ++cIbad_hdr; 1177 if (! ficheck_errors (qdaemon)) 1178 return FALSE; 1179 1180 fbadhdr = TRUE; 1181 } 1182 1183 iPrecstart = (iPrecstart + 1) % CRECBUFLEN; 1184 continue; 1185 } 1186 1187 zfirst = zsecond = NULL; 1188 cfirst = csecond = 0; 1189 1190 ttype = THDRCON_GETTYPE (ab[IHDR_CONTENTS1], ab[IHDR_CONTENTS2]); 1191 if (ttype == DATA || ttype == SPOS || ttype == CLOSE) 1192 iseq = IHDRWIN_GETSEQ (ab[IHDR_LOCAL]); 1193 else 1194 iseq = -1; 1195 csize = CHDRCON_GETBYTES (ab[IHDR_CONTENTS1], ab[IHDR_CONTENTS2]); 1196 1197 if (iseq != -1) 1198 { 1199 /* Make sure this packet is in our receive window. The last 1200 packet we have acked is iIlocal_ack. */ 1201 if (iIrequest_winsize > 0 1202 && CSEQDIFF (iseq, iIlocal_ack) > iIrequest_winsize) 1203 { 1204 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1205 "fiprocess_data: Out of order packet %d (ack %d)", 1206 iseq, iIlocal_ack); 1207 1208 ++cIbad_order; 1209 if (! ficheck_errors (qdaemon)) 1210 return FALSE; 1211 1212 iPrecstart = (iPrecstart + 1) % CRECBUFLEN; 1213 1214 continue; 1215 } 1216 } 1217 1218 if (csize > 0) 1219 { 1220 int cinbuf; 1221 char abcksum[CCKSUMLEN]; 1222 unsigned long ickdata; 1223 1224 cinbuf = iPrecend - iPrecstart; 1225 if (cinbuf < 0) 1226 cinbuf += CRECBUFLEN; 1227 if (cinbuf < CHDRLEN + csize + CCKSUMLEN) 1228 { 1229 if (pcneed != NULL) 1230 *pcneed = CHDRLEN + csize + CCKSUMLEN - cinbuf; 1231 return TRUE; 1232 } 1233 1234 if (iPrecend > iPrecstart) 1235 { 1236 cfirst = csize; 1237 zfirst = abPrecbuf + iPrecstart + CHDRLEN; 1238 } 1239 else 1240 { 1241 cfirst = CRECBUFLEN - (iPrecstart + CHDRLEN); 1242 if (cfirst <= 0) 1243 { 1244 /* Here cfirst is non-positive, so subtracting from 1245 abPrecbuf will actually skip the appropriate number 1246 of bytes at the start of abPrecbuf. */ 1247 zfirst = abPrecbuf - cfirst; 1248 cfirst = csize; 1249 } 1250 else 1251 { 1252 if (cfirst >= csize) 1253 cfirst = csize; 1254 else 1255 { 1256 zsecond = abPrecbuf; 1257 csecond = csize - cfirst; 1258 } 1259 zfirst = abPrecbuf + iPrecstart + CHDRLEN; 1260 } 1261 } 1262 1263 /* Get the checksum into abcksum. */ 1264 for (i = 0, iget = (iPrecstart + CHDRLEN + csize) % CRECBUFLEN; 1265 i < CCKSUMLEN; 1266 i++, iget = (iget + 1) % CRECBUFLEN) 1267 abcksum[i] = abPrecbuf[iget]; 1268 1269 ickdata = icrc (zfirst, (size_t) cfirst, ICRCINIT); 1270 if (csecond > 0) 1271 ickdata = icrc (zsecond, (size_t) csecond, ickdata); 1272 1273 if (ICKSUM_GET (abcksum) != ickdata) 1274 { 1275 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1276 "fiprocess_data: Bad checksum; data %lu, frame %lu", 1277 ickdata, ICKSUM_GET (abcksum)); 1278 1279 ++cIbad_cksum; 1280 if (! ficheck_errors (qdaemon)) 1281 return FALSE; 1282 1283 /* If this sequence number is in our receive window, 1284 send a NAK. iIrecseq is the last sequence number we 1285 have succesfully received. */ 1286 if (iseq != -1 1287 && iseq != iIrecseq 1288 && (iIrequest_winsize <= 0 1289 || CSEQDIFF (iseq, iIrecseq) <= iIrequest_winsize) 1290 && azIrecbuffers[iseq] == NULL) 1291 { 1292 if (! finak (qdaemon, iseq)) 1293 return FALSE; 1294 } 1295 1296 iPrecstart = (iPrecstart + 1) % CRECBUFLEN; 1297 continue; 1298 } 1299 } 1300 1301 /* Here we know that this is a valid packet, so we can adjust 1302 iPrecstart accordingly. */ 1303 if (csize == 0) 1304 iPrecstart = (iPrecstart + CHDRLEN) % CRECBUFLEN; 1305 else 1306 { 1307 iPrecstart = ((iPrecstart + CHDRLEN + csize + CCKSUMLEN) 1308 % CRECBUFLEN); 1309 ++cIreceived_packets; 1310 } 1311 1312 /* Get the ack from the packet, if appropriate. iIsendseq is 1313 the next sequence number we are going to send, and 1314 iIremote_ack is the last sequence number acknowledged by the 1315 remote system. */ 1316 iack = IHDRWIN_GETSEQ (ab[IHDR_REMOTE]); 1317 if (iIremote_winsize > 0 1318 && iack != iIsendseq 1319 && CSEQDIFF (iack, iIremote_ack) <= iIremote_winsize 1320 && CSEQDIFF (iIsendseq, iack) <= iIremote_winsize) 1321 { 1322 /* Call uwindow_acked each time packet 0 is acked. */ 1323 if (iack < iIremote_ack) 1324 uwindow_acked (qdaemon, FALSE); 1325 iIremote_ack = iack; 1326 } 1327 1328 if (iseq != -1) 1329 { 1330 /* If we already sent a NAK for this packet, and we have not 1331 seen the previous packet, then forget that we sent a NAK 1332 for this and any preceding packets. This is to handle 1333 the following sequence: 1334 receive packet 0 1335 packets 1 and 2 lost 1336 receive packet 3 1337 send NAK 1 1338 send NAK 2 1339 packet 1 lost 1340 receive packet 2 1341 At this point we want to send NAK 1. */ 1342 if (afInaked[iseq] 1343 && azIrecbuffers[IPREVSEQ (iseq)] == NULL) 1344 { 1345 for (i = INEXTSEQ (iIrecseq); 1346 i != iseq; 1347 i = INEXTSEQ (i)) 1348 afInaked[i] = FALSE; 1349 afInaked[iseq] = FALSE; 1350 } 1351 1352 /* If we haven't handled all previous packets, we must save 1353 off this packet and deal with it later. */ 1354 if (iseq != INEXTSEQ (iIrecseq)) 1355 { 1356 if (iseq == iIrecseq 1357 || (iIrequest_winsize > 0 1358 && CSEQDIFF (iseq, iIrecseq) > iIrequest_winsize)) 1359 { 1360 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1361 "fiprocess_data: Ignoring out of order packet %d (recseq %d)", 1362 iseq, iIrecseq); 1363 continue; 1364 } 1365 else 1366 { 1367 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1368 "fiprocess_data: Saving unexpected packet %d (recseq %d)", 1369 iseq, iIrecseq); 1370 1371 if (azIrecbuffers[iseq] == NULL) 1372 { 1373 azIrecbuffers[iseq] = zbufalc ((size_t) (CHDRLEN 1374 + csize)); 1375 memcpy (azIrecbuffers[iseq], ab, CHDRLEN); 1376 if (csize > 0) 1377 { 1378 memcpy (azIrecbuffers[iseq] + CHDRLEN, zfirst, 1379 (size_t) cfirst); 1380 if (csecond > 0) 1381 memcpy (azIrecbuffers[iseq] + CHDRLEN + cfirst, 1382 zsecond, (size_t) csecond); 1383 } 1384 } 1385 } 1386 1387 /* Send NAK's for each packet between the last one we 1388 received and this one, avoiding any packets for which 1389 we've already sent NAK's or which we've already 1390 received. */ 1391 for (i = INEXTSEQ (iIrecseq); 1392 i != iseq; 1393 i = INEXTSEQ (i)) 1394 { 1395 if (! afInaked[i] 1396 && azIrecbuffers[i] == NULL) 1397 { 1398 if (! finak (qdaemon, i)) 1399 return FALSE; 1400 } 1401 } 1402 1403 continue; 1404 } 1405 1406 iIrecseq = iseq; 1407 } 1408 1409 if (pffound != NULL) 1410 *pffound = TRUE; 1411 1412 if (! fiprocess_packet (qdaemon, ab, zfirst, cfirst, zsecond, csecond, 1413 pfexit)) 1414 return FALSE; 1415 1416 if (iseq != -1) 1417 { 1418 int inext; 1419 1420 /* If we've already received the next packet(s), process 1421 them. */ 1422 inext = INEXTSEQ (iIrecseq); 1423 while (azIrecbuffers[inext] != NULL) 1424 { 1425 char *z; 1426 int c; 1427 1428 z = azIrecbuffers[inext]; 1429 c = CHDRCON_GETBYTES (z[IHDR_CONTENTS1], z[IHDR_CONTENTS2]); 1430 iIrecseq = inext; 1431 if (! fiprocess_packet (qdaemon, z, z + CHDRLEN, c, 1432 (char *) NULL, 0, pfexit)) 1433 return FALSE; 1434 ubuffree (azIrecbuffers[inext]); 1435 azIrecbuffers[inext] = NULL; 1436 inext = INEXTSEQ (inext); 1437 } 1438 } 1439 1440 /* If we have received half of our window size or more since the 1441 last ACK, send one now. Sending an ACK for half the window 1442 at a time should significantly cut the acknowledgement 1443 traffic when only one side is sending. We should normally 1444 not have to send an ACK if we have data to send, since each 1445 packet sent will ACK the most recently received packet. 1446 However, it can happen if we receive a burst of short 1447 packets, such as a set of command acknowledgements. */ 1448 if (iIrequest_winsize > 0 1449 && CSEQDIFF (iIrecseq, iIlocal_ack) >= cIack_frequency) 1450 { 1451 char aback[CHDRLEN]; 1452 1453 aback[IHDR_INTRO] = IINTRO; 1454 aback[IHDR_LOCAL] = IHDRWIN_SET (0, 0); 1455 aback[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 1456 iIlocal_ack = iIrecseq; 1457 aback[IHDR_CONTENTS1] = IHDRCON_SET1 (ACK, qdaemon->fcaller, 0); 1458 aback[IHDR_CONTENTS2] = IHDRCON_SET2 (ACK, qdaemon->fcaller, 0); 1459 aback[IHDR_CHECK] = IHDRCHECK_VAL (aback); 1460 1461 DEBUG_MESSAGE1 (DEBUG_PROTO, "fiprocess_data: Sending ACK %d", 1462 iIrecseq); 1463 1464 if (! (*pfIsend) (qdaemon->qconn, aback, CHDRLEN, TRUE)) 1465 return FALSE; 1466 } 1467 } 1468 1469 if (pcneed != NULL) 1470 *pcneed = CHDRLEN; 1471 1472 return TRUE; 1473} 1474 1475/* Process a single packet. */ 1476 1477static boolean 1478fiprocess_packet (qdaemon, zhdr, zfirst, cfirst, zsecond, csecond, pfexit) 1479 struct sdaemon *qdaemon; 1480 const char *zhdr; 1481 const char *zfirst; 1482 int cfirst; 1483 const char *zsecond; 1484 int csecond; 1485 boolean *pfexit; 1486{ 1487 int ttype; 1488 1489 ttype = THDRCON_GETTYPE (zhdr[IHDR_CONTENTS1], zhdr[IHDR_CONTENTS2]); 1490 switch (ttype) 1491 { 1492 case DATA: 1493 { 1494 int iseq; 1495 boolean fret; 1496 1497 iseq = IHDRWIN_GETSEQ (zhdr[IHDR_LOCAL]); 1498 DEBUG_MESSAGE4 (DEBUG_PROTO, 1499 "fiprocess_packet: Got DATA packet %d size %d local %d remote %d", 1500 iseq, cfirst + csecond, 1501 IHDRWIN_GETCHAN (zhdr[IHDR_REMOTE]), 1502 IHDRWIN_GETCHAN (zhdr[IHDR_LOCAL])); 1503 fret = fgot_data (qdaemon, zfirst, (size_t) cfirst, 1504 zsecond, (size_t) csecond, 1505 IHDRWIN_GETCHAN (zhdr[IHDR_REMOTE]), 1506 IHDRWIN_GETCHAN (zhdr[IHDR_LOCAL]), 1507 iIrecpos, 1508 INEXTSEQ (iIremote_ack) == iIsendseq, 1509 pfexit); 1510 iIrecpos += cfirst + csecond; 1511 return fret; 1512 } 1513 1514 case SYNC: 1515 { 1516 int ipack, iwin, cchans; 1517 1518 /* We accept a SYNC packet to adjust the packet and window 1519 sizes at any time. */ 1520 if (cfirst + csecond < 3) 1521 { 1522 ulog (LOG_ERROR, "Bad SYNC packet"); 1523 return FALSE; 1524 } 1525 ipack = (zfirst[0] & 0xff) << 8; 1526 if (cfirst > 1) 1527 ipack |= zfirst[1] & 0xff; 1528 else 1529 ipack |= zsecond[0]; 1530 if (cfirst > 2) 1531 iwin = zfirst[2]; 1532 else 1533 iwin = zsecond[2 - cfirst]; 1534 1535 /* The fourth byte in a SYNC packet is the number of channels 1536 to use. This is optional. Switching the number of 1537 channels in the middle of a conversation may cause 1538 problems. */ 1539 if (cfirst + csecond <= 3) 1540 cchans = 0; 1541 else 1542 { 1543 if (cfirst > 3) 1544 cchans = zfirst[3]; 1545 else 1546 cchans = zsecond[3 - cfirst]; 1547 if (cchans > 0 && cchans < 8) 1548 qdaemon->cchans = cchans; 1549 } 1550 1551 DEBUG_MESSAGE3 (DEBUG_PROTO, 1552 "fiprocess_packet: Got SYNC packsize %d winsize %d channels %d", 1553 ipack, iwin, cchans); 1554 1555 if (iIforced_remote_packsize == 0 1556 && (iIalc_packsize == 0 1557 || ipack <= iIalc_packsize)) 1558 iIremote_packsize = ipack; 1559 iIremote_winsize = iwin; 1560 1561 /* We increment a static variable to tell the initialization 1562 code that a SYNC was received, and we set *pfexit to TRUE 1563 to get out to the initialization code (this will do no harm 1564 if we are called from elsewhere). */ 1565 ++cIsyncs; 1566 *pfexit = TRUE; 1567 return TRUE; 1568 } 1569 1570 case ACK: 1571 /* There is nothing to do here, since the ack was already 1572 handled in fiprocess_data. */ 1573 DEBUG_MESSAGE1 (DEBUG_PROTO, 1574 "fiprocess_packet: Got ACK %d", 1575 IHDRWIN_GETSEQ (zhdr[IHDR_REMOTE])); 1576 return TRUE; 1577 1578 case NAK: 1579 /* We must resend the requested packet. */ 1580 { 1581 int iseq; 1582 char *zsend; 1583 size_t clen; 1584 1585 ++cIremote_rejects; 1586 if (! ficheck_errors (qdaemon)) 1587 return FALSE; 1588 1589 iseq = IHDRWIN_GETSEQ (zhdr[IHDR_LOCAL]); 1590 1591 /* If the remote side times out while waiting for a packet, it 1592 will send a NAK for the next packet it wants to see. If we 1593 have not sent that packet yet, and we have no 1594 unacknowledged data, it implies that the remote side has a 1595 window full of data to send, which implies that our ACK has 1596 been lost. Therefore, we send an ACK. */ 1597 if (iseq == iIsendseq && 1598 INEXTSEQ (iIremote_ack) == iIsendseq) 1599 { 1600 char aback[CHDRLEN]; 1601 1602 aback[IHDR_INTRO] = IINTRO; 1603 aback[IHDR_LOCAL] = IHDRWIN_SET (0, 0); 1604 aback[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0); 1605 iIlocal_ack = iIrecseq; 1606 aback[IHDR_CONTENTS1] = IHDRCON_SET1 (ACK, qdaemon->fcaller, 0); 1607 aback[IHDR_CONTENTS2] = IHDRCON_SET2 (ACK, qdaemon->fcaller, 0); 1608 aback[IHDR_CHECK] = IHDRCHECK_VAL (aback); 1609 1610 DEBUG_MESSAGE1 (DEBUG_PROTO, "fiprocess_packet: Sending ACK %d", 1611 iIrecseq); 1612 1613 return (*pfIsend) (qdaemon->qconn, aback, CHDRLEN, TRUE); 1614 } 1615 else 1616 { 1617 if (iseq == iIsendseq 1618 || (iIremote_winsize > 0 1619 && (CSEQDIFF (iseq, iIremote_ack) > iIremote_winsize 1620 || CSEQDIFF (iIsendseq, iseq) > iIremote_winsize))) 1621 { 1622 DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL, 1623 "fiprocess_packet: Ignoring out of order NAK %d (sendseq %d)", 1624 iseq, iIsendseq); 1625 return TRUE; 1626 } 1627 1628 DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL, 1629 "fiprocess_packet: Got NAK %d; resending packet", 1630 iseq); 1631 1632 /* Update the received sequence number. */ 1633 zsend = azIsendbuffers[iseq] + CHDROFFSET; 1634 if (IHDRWIN_GETSEQ (zsend[IHDR_REMOTE]) != iIrecseq) 1635 { 1636 int iremote; 1637 1638 iremote = IHDRWIN_GETCHAN (zsend[IHDR_REMOTE]); 1639 zsend[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, iremote); 1640 zsend[IHDR_CHECK] = IHDRCHECK_VAL (zsend); 1641 iIlocal_ack = iIrecseq; 1642 } 1643 1644 ++cIresent_packets; 1645 1646 clen = CHDRCON_GETBYTES (zsend[IHDR_CONTENTS1], 1647 zsend[IHDR_CONTENTS2]); 1648 1649 return (*pfIsend) (qdaemon->qconn, zsend, 1650 CHDRLEN + clen + (clen > 0 ? CCKSUMLEN : 0), 1651 TRUE); 1652 } 1653 } 1654 1655 case SPOS: 1656 /* Set the file position. */ 1657 { 1658 char abpos[CCKSUMLEN]; 1659 const char *zpos; 1660 1661 if (cfirst >= CCKSUMLEN) 1662 zpos = zfirst; 1663 else 1664 { 1665 memcpy (abpos, zfirst, (size_t) cfirst); 1666 memcpy (abpos + cfirst, zsecond, (size_t) (CCKSUMLEN - cfirst)); 1667 zpos = abpos; 1668 } 1669 iIrecpos = (long) ICKSUM_GET (zpos); 1670 DEBUG_MESSAGE1 (DEBUG_PROTO, 1671 "fiprocess_packet: Got SPOS %ld", iIrecpos); 1672 return TRUE; 1673 } 1674 1675 case CLOSE: 1676 { 1677 boolean fexpected; 1678 1679 fexpected = ! fLog_sighup || fIclosing; 1680 if (! fexpected) 1681 ulog (LOG_ERROR, "Received unexpected CLOSE packet"); 1682 else 1683 DEBUG_MESSAGE0 (DEBUG_PROTO, "fiprocess_packet: Got CLOSE packet"); 1684 1685 fIclosing = TRUE; 1686 *pfexit = TRUE; 1687 return fexpected; 1688 } 1689 1690 default: 1691 /* Just ignore unrecognized packet types, for future protocol 1692 enhancements. */ 1693 DEBUG_MESSAGE1 (DEBUG_PROTO, "fiprocess_packet: Got packet type %d", 1694 ttype); 1695 return TRUE; 1696 } 1697 /*NOTREACHED*/ 1698} 1699