📄 dcpgpkt.c
字号:
/* */
/* flags = (flags & B_SENT_INITA) | B_RECV_INITA; */
/* */
/* works to turn off all the bits in flags except B_SENT_INITA */
/* if it was already on, and then turns on flag B_RECV_INITA. */
/* We use statements like this to reset most of the flags at */
/* once, leaving one or two bits on; this in turn allows us to */
/* check in later states that the previous two states were the */
/* expected ones. */
/* */
/* Likewise, the following statement: */
/* */
/* state = (flags & B_SENT_INITA) ? */
/* I_INITB_SEND : I_INITA_SEND; */
/* */
/* tests to see if B_SENT_INITA was already set, and return the */
/* "true" condition (I_INITB_SEND) otherwise return the "false" */
/* (I_INITA_SEND). */
/*--------------------------------------------------------------------*/
while( state != I_COMPLETE )
{
printmsg(4, "gopenpk: I State = %2d, flag = 0x%02x",
(int) state, (int) flags);
switch( state )
{
/*--------------------------------------------------------------------*/
/* Receive a packet */
/*--------------------------------------------------------------------*/
case I_GRPACK:
switch (grpack(&yyy, &xxx, &len, NULL, M_gPacketTimeout ))
{
case INITA:
printmsg(5, "**got INITA");
state = I_INITA_RECV;
break;
case INITB:
printmsg(5, "**got INITB");
state = I_INITB_RECV;
break;
case INITC:
printmsg(5, "**got INITC");
state = I_INITC_RECV;
break;
case DCP_EMPTY:
printmsg(GDEBUG, "**got EMPTY");
state = I_EMPTY;
if (bmodemflag[MODEM_CD] && !CD())
{
printmsg(0,"gopenpk: Modem carrier lost");
return DCP_FAILED;
}
break;
case CLOSE:
printmsg(GDEBUG, "**got CLOSE");
gspack(CLOSE, 0, 0, 0, 0, NULL);
return DCP_FAILED;
default:
printmsg(GDEBUG, "**got SCREW UP");
state = I_ERROR;
break;
}
if (bmodemflag[MODEM_CD] && !CD())
{
printmsg(0,"gopenpk: Modem carrier lost");
return DCP_FAILED;
}
break;
/*--------------------------------------------------------------------*/
/* Initialize states */
/*--------------------------------------------------------------------*/
case I_CALLER:
state = I_INITA_SEND;
break;
case I_CALLEE:
state = I_GRPACK;
break;
/*--------------------------------------------------------------------*/
/* Process received or sent packets */
/*--------------------------------------------------------------------*/
case I_INITA_RECV:
if (yyy < (short) nwindows)
{
nwindows = yyy;
rwu = nwindows - 1;
}
flags = (flags & B_SENT_INITA) | B_RECV_INITA;
state = (flags & B_SENT_INITA) ? I_INITB_SEND : I_INITA_SEND;
break;
case I_INITA_SEND:
gspack(INITA, 0, 0, 0, nwindows, NULL);
flags = (flags & B_RECV_INITA) | B_SENT_INITA;
state = I_GRPACK;
break;
case I_INITB_RECV:
if ((flags & (B_RECV_INITA | B_SENT_INITA)) ==
(B_RECV_INITA | B_SENT_INITA))
{
i = (short) 8 * (2 << (yyy+1));
if (i < (short) s_pktsize)
s_pktsize = i;
flags = (flags & B_SENT_INITB) | B_RECV_INITB;
state = (flags & B_SENT_INITB) ? I_INITC_SEND : I_INITB_SEND;
} /* if */
else
state = I_RESTART;
break;
case I_INITB_SEND:
gspack(INITB, 0, 0, 0, r_pktsize, NULL);
/* Data segment (packet) size */
flags = (flags & (B_INITA | B_RECV_INITB)) | B_SENT_INITB;
state = I_GRPACK;
break;
case I_INITC_RECV:
if ((flags & (B_RECV_INITB | B_SENT_INITB)) ==
(B_RECV_INITB | B_SENT_INITB))
{
if (yyy < (short) nwindows)
{
printmsg(0,"Unexpected INITC window size of %d",
nwindows );
nwindows = yyy;
rwu = nwindows - 1;
}
flags = (flags & B_SENT_INITC) | B_RECV_INITC;
state = (flags & B_SENT_INITC) ? I_COMPLETE : I_INITC_SEND;
}
else
state = I_RESTART;
break;
case I_INITC_SEND:
gspack(INITC, 0, 0, 0, nwindows, NULL);
flags = (flags & (B_INITB | B_RECV_INITC)) | B_SENT_INITC;
state = (flags & B_RECV_INITC) ? I_COMPLETE : I_GRPACK;
break;
/*--------------------------------------------------------------------*/
/* Error states */
/*--------------------------------------------------------------------*/
case I_EMPTY:
timeouts++;
state = I_RESTART;
break;
case I_ERROR:
screwups++;
state = I_RESTART;
break;
case I_RESTART:
printmsg(2,"gopenpk: Restarting initialize sequence");
nerr++;
flags = 0x00;
state = I_INITA_SEND;
break;
} /* switch */
if ( terminate_processing )
{
printmsg(0,"gopenpk: Terminated by user");
return DCP_FAILED;
}
if (nerr >= M_MaxErr)
{
remote_stats.errors += nerr;
nerr = 0;
printmsg(0,
"gopenpk: Consecutive error limit of %ld exceeded, "
"%ld total errors",
(long) M_MaxErr, remote_stats.errors);
return(DCP_FAILED);
}
} /* while */
/*--------------------------------------------------------------------*/
/* Allocate the needed buffers */
/*--------------------------------------------------------------------*/
grpkt = realloc( grpkt, r_pktsize + HDRSIZE );
checkref( grpkt );
#if !defined(BIT32ENV)
gspkt = malloc( s_pktsize );
checkref( gspkt );
#endif
nerr = 0;
lazynak = 0;
#if defined(BIT32ENV) || defined(_Windows)
printmsg(2,"%s packets, "
"Window size %d, "
"Receive packet %d, "
"Send packet %d",
variablepacket ? "Variable" : "Fixed",
nwindows,
r_pktsize,
s_pktsize );
#else
printmsg(2,"%s packets, "
"Window size %d, "
"Receive packet %d, "
"Send packet %d, "
"Memory avail %u",
variablepacket ? "Variable" : "Fixed",
nwindows,
r_pktsize,
s_pktsize,
memavail());
#endif
return(DCP_OK); /* channel open */
} /*initialize*/
/*--------------------------------------------------------------------*/
/* g f i l e p k t */
/* */
/* Begin a file transfer (not used by "g" protocol) */
/*--------------------------------------------------------------------*/
short gfilepkt( void )
{
return DCP_OK;
} /* gfilepkt */
/*--------------------------------------------------------------------*/
/* g c l o s e p k */
/* */
/* Close packet machine */
/*--------------------------------------------------------------------*/
short gclosepk()
{
unsigned short i;
for (i = 0; i < MAXTRY; i++)
{
gspack(CLOSE, 0, 0, 0, 0, NULL);
if (gmachine(M_gPacketTimeout) == CLOSE)
break;
} /* for (i = 0; i < MAXTRY; i++) */
/*--------------------------------------------------------------------*/
/* Release our buffers */
/*--------------------------------------------------------------------*/
free( grpkt );
grpkt = NULL;
#if !defined(BIT32ENV)
free( gspkt );
gspkt = NULL;
#endif
/*--------------------------------------------------------------------*/
/* Report the results of our adventures */
/*--------------------------------------------------------------------*/
gstats();
/*--------------------------------------------------------------------*/
/* Return to caller */
/*--------------------------------------------------------------------*/
return(0);
} /*gclosepk*/
/*--------------------------------------------------------------------*/
/* g s t a t s */
/* */
/* Report summary of errors for processing */
/*--------------------------------------------------------------------*/
static void gstats( void )
{
remote_stats.errors += nerr;
nerr = 0;
if ( remote_stats.errors || badhdr )
{
printmsg(0,
"%d time outs, %d port reinits, %d out of seq pkts, "
"%d NAKs rec, %d NAKs sent",
timeouts, reinit, outsequence, naksin, naksout);
printmsg(0,
"%d invalid pkt types, %d re-syncs, %d bad pkt hdrs, %d pkts resent",
screwups, shifts, badhdr, resends);
} /* if ( remote_stats.errors || shifts || badhdr ) */
} /* gstats */
/*--------------------------------------------------------------------*/
/* g g e t p k t */
/* */
/* Gets no more than a packet's worth of data from */
/* the "packet I/O state machine". May have to */
/* periodically run the packet machine to get some packets. */
/* */
/* on input: don't care */
/* on return: data+\0 and length in len. */
/* */
/* ret(0) if all's well */
/* ret(-1) if problems (failed) */
/*--------------------------------------------------------------------*/
short ggetpkt(char *data, short *len)
{
short retry = M_MaxErr;
time_t start;
#ifdef _DEBUG
short savedebug = debuglevel;
#endif
irec = 1;
checkref( data );
/*--------------------------------------------------------------------*/
/* Loop to wait for the desired packet */
/*--------------------------------------------------------------------*/
time( &start );
while (!arrived[rbl] && retry)
{
if (gmachine(M_gPacketTimeout) != POK)
return(-1);
if (!arrived[rbl] )
{
time_t now;
if (time( &now ) > (start + M_gPacketTimeout) )
{
#ifdef _DEBUG
if ( debuglevel < 6 )
debuglevel = 6;
#endif
printmsg(GDEBUG,
"ggetpkt: Timeout %d waiting for inbound packet %d",
M_MaxErr - --retry, remote_stats.packets + 1);
timeouts++;
start = now;
} /* if (time( now ) > (start + M_gPacketTimeout) ) */
} /* if (!arrived[rbl] ) */
} /* while (!arrived[rbl] && i) */
#ifdef _DEBUG
debuglevel = savedebug;
#endif
if (!arrived[rbl])
{
printmsg(0,"ggetpkt: Remote host failed to respond after %ld seconds",
(long) M_gPacketTimeout * M_MaxErr);
gclosepk();
return -1;
}
/*--------------------------------------------------------------------*/
/* Got a packet! */
/*--------------------------------------------------------------------*/
*len = inlen[rbl];
MEMCPY(data, inbuf[rbl], *len);
arrived[rbl] = FALSE; /* Buffer is now emptied */
rwu = nextpkt(rwu); /* bump receive window */
return(0);
} /*ggetpkt*/
/*
g s e n d p k t
Put at most a packet's worth of data in the packet state
machine for transmission.
May have to run the packet machine a few times to get
an available output slot.
on input: data=*data; len=length of data in data.
return:
0 if all's well
-1 if problems (failed)
*/
short gsendpkt(char *data, short len)
{
short delta;
#ifdef _DEBUG
short savedebug = debuglevel;
#endif
checkref( data );
irec = 0;
/*--------------------------------------------------------------------*/
/* WAIT FOR INPUT i.e. if we have sent SWINDOW pkts and none */
/* have been acked, wait for acks. Note that we always go */
/* through the machine at least once to keep caught up with */
/* ACK's sent by remote machine. */
/*--------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -