📄 dcpgpkt.c
字号:
/*--------------------------------------------------------------------*/
/* d c p g p k t . c */
/* */
/* UUCP 'g' protocol module for UUPC/extended. Supports 7 */
/* window variable length packets of up yo 512 bytes in */
/* length. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Stuart Lynne May/87 */
/* */
/* Copyright (c) Richard H. Lamb 1985, 1986, 1987 */
/* Changes Copyright (c) Stuart Lynne 1987 */
/* */
/* Changes Copyright (c) 1989-1993 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by the */
/* UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: dcpgpkt.c 1.18 1993/10/04 03:57:20 ahd Exp $
*
* $Log: dcpgpkt.c $
* Revision 1.18 1993/10/04 03:57:20 ahd
* Drop new lines from start up message
*
* Revision 1.17 1993/10/02 22:56:59 ahd
* Suppress compile warning
*
* Revision 1.16 1993/10/02 19:07:49 ahd
* Treat Windows 3.x ala DOS in handling packets in far memory
*
* Revision 1.15 1993/09/20 04:41:54 ahd
* OS/2 2.x support
*
* Revision 1.14 1993/07/22 23:22:27 ahd
* First pass at changes for Robert Denny's Windows 3.1 support
*
* Revision 1.13 1993/05/30 00:01:47 ahd
* Move UUFAR into header file
*
* Revision 1.12 1993/04/13 03:19:45 ahd
* Only perform copy to gspkt if input to gsendpkt is non-null
*
* Revision 1.11 1993/04/13 03:00:05 ahd
* Correct gspkt declare
*
* Revision 1.10 1993/04/13 02:26:30 ahd
* Move buffers to FAR memory
*
* Revision 1.9 1993/04/05 04:32:19 ahd
* Allow unique send and receive packet sizes
*
* Revision 1.8 1993/03/06 23:04:54 ahd
* Make state names more descriptive
*
* Revision 1.7 1992/11/21 05:55:11 ahd
* Use single bit field for gopenpk flag bits, add debugging info
*
* Revision 1.6 1992/11/20 12:38:39 ahd
* Add additional flags to avoid prematurely ending init sequence
*
* Revision 1.5 1992/11/19 03:00:29 ahd
* drop rcsid
*
* Revision 1.4 1992/11/17 13:45:37 ahd
* Add comments from Ian Talyor
*
* Revision 1.3 1992/11/16 02:10:27 ahd
* Rewrite protocol initialize to insure full exchange of packets
*
* 25Aug87 - Allow for up to 7 windows - Jal
*
* 01Nov87 - those strncpy's should really be memcpy's! -
* Jal
*
* 11Sep89 - Raise TimeOut to 15 - ahd
*
* 30Apr90 - Add Jordon Brown's fix for short packet
* retries. Reduce retry limit to 20
*
* 22Jul90 - Change error retry limit from per host to per
* packet.
*
* 22Jul90 - Add error message for number of retries
* exceeded
*
* 08Sep90 - Drop memmove to memcpy change supplied by
* Jordan Brown, MS 6.0 and Turbo C++ agree
* memmove insures no overlap
*/
/*--------------------------------------------------------------------*/
/* Thanks goes to John Gilmore for sending me a copy of Greg */
/* Chesson's UUCP protocol description -- Obviously invaluable. */
/* Thanks also go to Andrew Tannenbaum for the section on */
/* Siding window protocols with a program example in his */
/* "Computer Networks" book. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef __TURBOC__
#include <mem.h>
#include <alloc.h>
#else
#include <malloc.h>
#endif
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "dcp.h"
#include "dcpsys.h"
#include "dcpgpkt.h"
#include "hostable.h"
#include "security.h"
#include "commlib.h"
#include "modem.h"
#include "catcher.h"
/*--------------------------------------------------------------------*/
/* Local defines */
/*--------------------------------------------------------------------*/
#define PKTSIZE MAXPACK
#define MINPKT 32
#define HDRSIZE 6
#define MAXTRY 4
#ifndef GDEBUG
#define GDEBUG 4
#endif
#ifdef __OS2__
#pragma warn -sig
#endif
/*--------------------------------------------------------------------*/
/* Control whether some buffers are placed outside the default */
/* data segment */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#define memavail coreleft
#else
#define memavail stackavail
#endif
/*--------------------------------------------------------------------*/
/* g-packet type definitions */
/*--------------------------------------------------------------------*/
#define DATA 0
#define CLOSE 1
#define NAK 2
#define SRJ 3
#define ACK 4
#define INITC 5
#define INITB 6
#define INITA 7
#define POK -1
#define MAXWINDOW 7
#define NBUF 8 /* always SAME as MAXSEQ ? */
#define MAXSEQ 8
typedef enum {
I_EMPTY,
I_ERROR,
I_RESTART,
I_CALLEE,
I_CALLER,
I_GRPACK,
I_INITA_RECV,
I_INITA_SEND,
I_INITB_RECV,
I_INITB_SEND,
I_INITC_RECV,
I_INITC_SEND,
I_COMPLETE
} I_STATE;
#define between(a,b,c) ((a<=b && b<c) || \
(c<a && a<=b) || \
(b<c && c<a))
#define nextpkt(x) ((x + 1) % MAXSEQ)
#define nextbuf(x) ((x + 1) % (nwindows+1))
/*--------------------------------------------------------------------*/
/* Handle 16 bit vs. 32 bit compilers */
/*--------------------------------------------------------------------*/
#if defined(BIT32ENV)
#define MEMSET(p,c,l) memset(p,c,l)
#define MEMCPY(t,s,l) memcpy(t,s,l)
#define MEMMOVE(t,s,l) memmove(t,s,l)
#else
#define MEMSET(p,c,l) _fmemset(p,c,l)
#define MEMCPY(t,s,l) _fmemcpy(t,s,l)
#define MEMMOVE(t,s,l) _fmemmove(t,s,l)
#endif
/*--------------------------------------------------------------------*/
/* Global variables for packet definitions */
/*--------------------------------------------------------------------*/
currentfile();
static short rwl, swl, swu, rwu, irec, lazynak;
static unsigned short nbuffers;
static short rbl, sbl, sbu;
static KEWSHORT nerr;
static unsigned short outlen[NBUF], inlen[NBUF], xmitlen[NBUF];
static boolean arrived[NBUF];
static size_t nwindows;
static char UUFAR outbuf[NBUF][MAXPACK];
static char UUFAR inbuf[NBUF][MAXPACK];
static time_t ftimer[NBUF];
static short timeouts, outsequence, naksin, naksout, screwups;
static short reinit, shifts, badhdr, resends;
static unsigned char *grpkt = NULL;
#if !defined(BIT32ENV)
static char *gspkt = NULL; // Local buffer dir
#endif
static boolean variablepacket; /* "v" or in modem file */
/*--------------------------------------------------------------------*/
/* Internal function prototypes */
/*--------------------------------------------------------------------*/
static short initialize(const boolean caller, const char protocol );
static short gmachine(const short timeout);
static void gspack(short type,
short yyy,
short xxx,
short len,
unsigned short xmit,
char UUFAR *data);
static short grpack(short *yyy,
short *xxx,
short *len,
char UUFAR *data,
const short timeout);
static void gstats( void );
static unsigned short checksum(char *data, short len);
/****************** SUB SUB SUB PACKET HANDLER ************/
/*--------------------------------------------------------------------*/
/* g o p e n p k */
/* */
/* Initialize processing for protocol */
/*--------------------------------------------------------------------*/
short Gopenpk(const boolean caller)
{
return initialize(caller , 'G');
} /* Gopenpk */
/*--------------------------------------------------------------------*/
/* v o p e n p k */
/* */
/* Initialize processing for protocol */
/*--------------------------------------------------------------------*/
short vopenpk(const boolean caller)
{
return initialize(caller, 'v');
} /* vopenpk */
/*--------------------------------------------------------------------*/
/* g o p e n p k */
/* */
/* Initialize processing for protocol */
/*--------------------------------------------------------------------*/
short gopenpk(const boolean caller)
{
return initialize(caller, 'g');
} /* vopenpk */
/*--------------------------------------------------------------------*/
/* i n i t i a l i z e */
/* */
/* Initialize processing for protocol */
/*--------------------------------------------------------------------*/
static short initialize(const boolean caller, const char protocol )
{
short i, xxx, yyy, len, maxwindows;
#define B_SENT_INITA 0x01
#define B_SENT_INITB 0x02
#define B_SENT_INITC 0x04
#define B_RECV_INITA 0x10
#define B_RECV_INITB 0x20
#define B_RECV_INITC 0x40
#define B_INITA (B_SENT_INITA | B_RECV_INITA)
#define B_INITB (B_SENT_INITB | B_RECV_INITB)
#define B_INITC (B_SENT_INITC | B_RECV_INITC)
short flags = 0x00; /* Init state flags, as defined above */
I_STATE state;
/*--------------------------------------------------------------------*/
/* Read modem file values for the number of windows and packet */
/* sizes */
/*--------------------------------------------------------------------*/
r_pktsize = s_pktsize = GetGPacket( MAXPACK, protocol );
maxwindows = GetGWindow(
min( MAXWINDOW, RECV_BUF / (s_pktsize+HDRSIZE)),
protocol);
variablepacket = bmodemflag[MODEM_VARIABLEPACKET] || (protocol == 'v');
grpkt = malloc( r_pktsize + HDRSIZE );
/*--------------------------------------------------------------------*/
/* Initialize error counters */
/*--------------------------------------------------------------------*/
timeouts = outsequence = naksin = naksout = screwups =
shifts = badhdr = resends = reinit = 0;
/*--------------------------------------------------------------------*/
/* Initialize proto parameters */
/*--------------------------------------------------------------------*/
nerr = nbuffers = 0;
sbl = swl = swu = sbu = 1;
rbl = rwl = 0;
nwindows = maxwindows;
rwu = nwindows - 1;
for (i = 0; i < NBUF; i++)
{
ftimer[i] = 0;
arrived[i] = FALSE;
}
/*--------------------------------------------------------------------*/
/* 3-way handshake */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* The three-way handshake should be independent of who */
/* initializes it, but it seems that some versions of uucico */
/* assume that the caller sends first and the callee responds. */
/* This only matters if we are the callee and the first packet */
/* is garbled. If we send a packet, the other side will assume */
/* that we must have seen the packet they sent and will never */
/* time out and send it again. Therefore, if we are the callee */
/* we don't send a packet the first time through the loop. */
/* This can still fail, but should usually work, and, after */
/* all, if the initialization packets are received correctly */
/* there will be no problem no matter what we do. */
/* */
/* (The above quoted verbatim from Ian Taylor) */
/*--------------------------------------------------------------------*/
state = caller ? I_CALLER : I_CALLEE;
/*--------------------------------------------------------------------*/
/* Exchange initialization messages with the other system. */
/* */
/* A problem: */
/* */
/* We send INITA; it gets received */
/* We receive INITA */
/* We send INITB; it gets garbled */
/* We receive INITB */
/* */
/* We have seen and sent INITB, so we start to send INITC. The */
/* other side as sent INITB but not seen it, so it times out */
/* and resends INITB. We will continue sending INITC and the */
/* other side will continue sending INITB until both sides give */
/* up and start again with INITA. */
/* */
/* It might seem as though if we are sending INITC and receive */
/* INITB, we should resend our INITB, but this could cause */
/* infinite echoing of INITB on a long-latency line. Rather */
/* than risk that, I have implemented a fast drop-back */
/* procedure. If we are sending INITB and receive INITC, the */
/* other side has gotten ahead of us. We immediately fail and */
/* begin again with INITA. For the other side, if we are */
/* sending INITC and see INITA, we also immediately fail back */
/* to INITA. */
/* */
/* Unfortunately, this doesn't work for the other case, in */
/* which we are sending INITB but the other side has not yet */
/* seen INITA. As far as I can see, if this happens we just */
/* have to wait until we time out and resend INITA. */
/* */
/* (The above also quoted verbatim from Ian Taylor; however, the */
/* code and associated bugs are all Drew's) */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* A note about the games with the variable "flags", which is */
/* bit twiddled alot below. The statement below: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -