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