home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
newc_dev
/
uucicosd.lha
/
gio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-02
|
21KB
|
1,009 lines
/*
* GIO.C WINDOWED G PROTOCOL
*
* written from scratch, except the checksum routine which was
* rewritten but based on the old one.
*
* WINDOW SIZE: When changing the window size be sure there
* are enough buffers available for pending txs.
*
* GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
* extended to window size of 7 by Jack J. Rouse
*
* Added variable packetsize (SegSize, TxSegSize). <CB>
*
*/
#include "includes.h"
typedef unsigned char ubyte;
typedef unsigned short uword;
typedef struct {
ubyte Dle; /* Literal ASCII DLE */
ubyte K; /* data size 2^(K+4) except K=0 means no data */
ubyte CL,CH; /* MAGIC - chksum(data) ^ C */
ubyte C;
ubyte X; /* K ^ C0 ^ C1 ^ C */
} Frame;
typedef struct {
ubyte CType; /* bits 7-6 of C */
ubyte CCmd; /* bits 5-3 of C */
ubyte CSeq; /* bits 2-0 of C */
ubyte PLen; /* pre-data (2 bytes) for SHORTDATA type */
ubyte *Data; /* implies CType=LONGDATA or SHORTDATA */
uword DLen; /* length of data */
} Packet;
Prototype int gwrdata(FILE *);
Prototype int gwrmsg(char *);
Prototype int grddata(FILE *);
Prototype int grdmsg(char *, int);
Prototype int gturnon(int);
Prototype int gturnoff(void);
Prototype void ResetGIO(void);
Prototype short ReducedTimeout;
short ReducedTimeout;
Local char *GetTxBuf(void);
Local int SendDataPacket(unsigned char *, int);
Local int RecvDataPacket(char **);
Local int GetData(int, Packet *);
Local int RecvdAck(char);
Local int WriteCtlPacket(int);
Local int WritePacket(Packet *, int);
Local int ReadPacket(Packet *, int, int);
Local int CheckSum(unsigned char *, int);
Local void FrameToPacket(Frame *, Packet *, unsigned char *);
Local int LenToK(unsigned short);
extern int debug;
extern int WindowSize;
extern int SegSize;
#define SUCCESS 0
#define FAIL 1
#define MAGIC 0125252
#define DLE 0x10
#define WINDOWSIZE 7
#define SEGSIZEK 2 /* 64 bytes ?? */
#define SEGSIZEMAX 9 /* 4096 bytes max <CB> */
#define SUB1(var) (((var)-1)&7)
#define CT_CONTROL (0 << 6)
#define CT_ALTCHN (1 << 6)
#define CT_LONGDATA (2 << 6)
#define CT_SHORTDATA (3 << 6)
#define CT_MASK (3 << 6)
#define CC_CLOSE (1 << 3)
#define CC_RJ (2 << 3)
#define CC_SRJ (3 << 3)
#define CC_RR (4 << 3)
#define CC_INITC (5 << 3)
#define CC_INITB (6 << 3)
#define CC_INITA (7 << 3)
#define CC_MASK (7 << 3)
#define SEQ_MASK 7
#define WAIT_ACK 1
#define WAIT_DATA 2
#define WAIT_CONTROL 3
#define MaxPktSize 4096
char RxBuf[MaxPktSize+4];
char *TxBuf[8];
/* TRANSMIT STAGE */
char TxSeq = 0; /* Last send packet */
char TxPend= 0; /* hasn't been acked yet */
uword TxWinSize; /* 1 or 2 (max 7) */
uword TxSegSize; /* maximum segment size */
char TxSegK; /* K for TxSegSize */
Packet TxPacket[8]; /* contents of last packet */
/* RECEIVE STAGE */
char RxSeq = 0; /* Last valid recv pkt */
char RxRdy = 0; /* Has come in.. */
char RxRetry = 8;
char RxNotAcked = 0; /* We have yet to ack it */
Packet RxPacket; /* The packet that has come in */
long Tot_Retries;
long Tot_Packets;
void
ResetGIO()
{
TxSeq = 0;
TxPend= 0;
TxWinSize = 0;
TxSegSize = 0;
TxSegK = 0;
RxSeq = 0;
RxRdy = 0;
RxRetry = 8;
RxNotAcked = 0;
}
/*
* Get Transmit Buffer. Note that some space to the left is available
*/
Local
char *
GetTxBuf()
{
static int index = 0;
if (++index > TxWinSize)
index = 0;
if (TxBuf[index] == NULL
&& (TxBuf[index] = (char *)malloc(MaxPktSize+4)) == NULL)
{
printf("Out of memory in GetTxBuf.");
/* could handle this case better, but it should be rare */
xexit(1);
}
return(TxBuf[index] + 2);
}
int
gwrdata(fi)
FILE *fi;
{
int bytes;
if (debug > 7)
printf("GWRDATA: ");
for (;;) {
char *buf = GetTxBuf();
if ((bytes = fread(buf, 1, TxSegSize, fi)) <= 0)
break;
BytesOut += bytes;
if (SendDataPacket(buf, bytes) != SUCCESS) {
if (debug > 7)
printf("GWR Failed\n");
return(FAIL);
}
if (debug > 7)
printf("\nGWROK ");
}
{
char *buf = GetTxBuf();
if (SendDataPacket(buf, 0) != SUCCESS) {
if (debug > 7)
printf("GWR Failed (last)\n");
return(FAIL);
}
}
if (debug > 7)
printf("\nGWFile Last Ack\n");
while (TxPend) {
if (GetData(WAIT_ACK, NULL) == FAIL)
return(FAIL);
}
if (debug > 7)
printf("success\n");
return (SUCCESS);
}
/*
* Write message to the other guy.
*
* NOTE: LONGDATA packets used exclusively and \0 fill to end.
*/
int
gwrmsg(str)
char *str;
{
int len = strlen(str) + 1; /* type + str + \0 */
if (debug > 7)
printf("GWRMSG: %s\n", str);
while (len > TxSegSize) {
char *buf = GetTxBuf();
movmem(str, buf, TxSegSize);
if (debug > 7)
printf("GWR-SEND %d\n", TxSegSize);
if (SendDataPacket(buf, TxSegSize) != SUCCESS)
return(FAIL);
len -= TxSegSize;
str += TxSegSize;
}
/*
* Find optimal packet size (remember, we must force LONGDATA
*
* Apparently packet sizes less than the agreed upon size are
* not allowed ???
*/
{
short siz = TxSegSize;
char *buf = GetTxBuf();
#ifdef NOTDEF
short k = TxSegK;
while (k > 1 && (siz >> 1) >= len) {
--k;
siz >>= 1;
}
#endif
if (debug > 7)
printf("GWR-FNL %d %d\n", len, siz);
movmem(str, buf, len);
setmem(buf + len, siz - len, 0);
if (SendDataPacket(buf, siz) != SUCCESS) {
if (debug > 7)
printf("GWR-FAIL\n");
return(FAIL);
}
}
if (debug > 7)
printf("GWR Last Ack\n");
while (TxPend) {
if (GetData(WAIT_ACK, NULL) == FAIL)
return(FAIL);
}
if (debug > 7)
printf("success\n");
return (SUCCESS);
}
int
grddata(fi)
FILE *fi;
{
int bytes;
char *buf;
if (debug > 7)
printf("GRDDATA\n");
while ((bytes = RecvDataPacket(&buf)) > 0) {
if (debug > 7)
printf("GRDDATA blk %d\n", bytes);
fwrite(buf, 1, bytes, fi);
BytesIn += bytes;
}
if (debug > 7)
printf("GRDDATA end %d\n", bytes);
if (bytes < 0)
return(FAIL);
else
return(SUCCESS);
}
int
grdmsg(buf, maxlen)
char *buf;
{
short i;
short n;
short slen;
char *ptr;
i = 0;
if (debug > 7)
printf("GRDMSG\n");
while ((n = RecvDataPacket(&ptr)) > 0) {
ptr[n] = 0;
slen = strlen(ptr);
if (slen > maxlen - 1) {
printf("GRDMSG: Buffer overflow!\n");
return (FAIL);
}
movmem(ptr, buf + i, slen);
buf[i + slen] = 0;
if (slen != n)
break;
i += slen;
maxlen -= slen;
}
if (debug > 7)
printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
if (n < 0) {
buf[0] = 0;
return(FAIL);
}
return(SUCCESS);
}
Local
int
SendDataPacket(buf, bytes)
ubyte *buf;
int bytes;
{
Packet P;
/*
* If window exhausted we must wait for at least one ack.
*/
while (TxPend == TxWinSize) {
if (GetData(WAIT_ACK, NULL) == FAIL)
return(FAIL);
}
TxSeq = (TxSeq + 1) & 7; /* next Tx packet */
/*
* Figure out best fit packet size. Apparently packets smaller
* then the agreed upon size are not allowed ???
*/
#ifdef NOTDEF
{
short k = TxSegK;
P.DLen = TxSegSize;
while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
--k;
P.DLen >>= 1;
}
}
#else
P.DLen = TxSegSize;
#endif
if (bytes < P.DLen) {
uword extra = P.DLen - bytes;
setmem(buf + bytes, extra, 0);
if (extra <= 127) {
P.PLen = 1;
buf[-1] = extra;
} else {
P.PLen = 2;
buf[-2] = 0x80 | extra;
buf[-1] = (extra >> 7);
}
P.CType = CT_SHORTDATA;
} else {
P.PLen = 0;
P.CType = CT_LONGDATA;
}
P.CCmd = TxSeq << 3; /* transmit sequence number */
P.CSeq = RxSeq; /* last valid received pkt */
P.Data = buf;
if (debug > 7)
printf("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
#ifdef NOTDEF
RxNotAcked = 0; /* We've acked the rx packet */
#else
if (RxNotAcked) { /* always send CC_RR packets */
WriteCtlPacket(CC_RR | RxSeq);
RxNotAcked = 0;
}
#endif
TxPacket[TxSeq] = P;
++TxPend;
WritePacket(&TxPacket[TxSeq], 1);
++Tot_Packets;
return(SUCCESS);
}
Local
int
RecvDataPacket(pbuf)
char **pbuf;
{
if (RxRdy == 0) {
if (GetData(WAIT_DATA, NULL) != SUCCESS)
return(-1);
}
*pbuf = RxPacket.Data;
RxRdy = 0;
return((int)RxPacket.DLen);
}
int
gturnon(master)
int master;
{
Packet P;
short retry = 5;
short windowsize = WINDOWSIZE; /* our prefered window size */
short segsize = SEGSIZEK; /* our prefered segment size */
if (WindowSize < windowsize) /* command line override */
windowsize = WindowSize;
if (SegSize > segsize && SegSize < SEGSIZEMAX)
segsize = SegSize; /* added by <CB> */
if (debug > 0)
printf("Proposed SegSize is %d\n", segsize);
if (master) {
while (retry > 0) {
WriteCtlPacket(CC_INITA | windowsize);
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
if (P.CSeq && P.CSeq < windowsize)
windowsize = P.CSeq;
break;
}
--retry;
}
while (retry > 0) {
WriteCtlPacket(CC_INITB | (segsize - 1));
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
if (P.CSeq < segsize - 1)
segsize = P.CSeq + 1;
break;
}
--retry;
}
while (retry > 0) {
WriteCtlPacket(CC_INITC | windowsize);
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
if (P.CSeq && P.CSeq < windowsize)
windowsize = P.CSeq;
break;
}
--retry;
}
} else {
while (retry > 0) {
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
WriteCtlPacket(CC_INITA | windowsize);
if (P.CSeq && windowsize > P.CSeq)
windowsize = P.CSeq;
break;
}
--retry;
}
while (retry > 0) {
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
WriteCtlPacket(CC_INITB | (segsize - 1));
if (P.CSeq < segsize - 1)
segsize = P.CSeq + 1;
break;
}
--retry;
}
while (retry > 0) {
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
WriteCtlPacket(CC_INITC | windowsize);
if (P.CSeq && windowsize > P.CSeq)
windowsize = P.CSeq;
break;
}
--retry;
}
}
TxSegK = segsize;
TxSegSize = 1 << (TxSegK + 4);
TxWinSize = windowsize;
xfer.proto[0] = 'g';
xfer.proto[1] = TxWinSize;
xfer.proto[2] = TxSegK;
if (debug > 0) {
printf("Window Size is %d\n", TxWinSize);
printf("Segment Size is %d (%d bytes)\n", TxSegK, TxSegSize);
}
if (retry == 0)
return(FAIL);
return(SUCCESS);
}
int
gturnoff()
{
Packet P;
short retry = 5;
if (RxNotAcked) { /* ack last data packet sent (presumably master's HY) */
WriteCtlPacket(CC_RR | RxSeq);
RxNotAcked = 0;
}
while (retry > 0) {
WriteCtlPacket(CC_CLOSE);
if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE)
return (SUCCESS);
--retry;
}
return (FAIL);
}
/*
* GetData()
*
* This is the core of the packet protocol. As soon as we get a satisfactory
* terminating condition we return. However, on unsatisfactory conditions
* such as having to send a reject, we attempt to drain any pending data
* (i.e. multiple returned rejects) so we do not do multiple resends.
*
* The resend flag only applies on a failure return.
*/
Local
int
GetData(waitfor, p)
int waitfor;
Packet *p;
{
Packet P;
short timeout;
short drainmode = 0;
/*
* If we haven't acked the last packet we received we must do
* so now before we can expect to receive another one!
*/
if (debug > 7)
printf("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
if (waitfor == WAIT_ACK)
timeout = (PacketTimeout) ? PacketTimeout : 5;
else if (waitfor == WAIT_DATA)
timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
else
timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
for (;;) {
/*
* due to confusion on connection termination, we do not wait
* around trying to retry the final termination acknowlege.
*/
if (ReducedTimeout) {
if (RxRetry > 2)
RxRetry = 2;
if (timeout > 5)
timeout = 5;
}
if (RxNotAcked) { /* good, send ack for rx'd pkt */
WriteCtlPacket(CC_RR | RxSeq);
RxNotAcked = 0;
} /* bad, timeout on read */
if (ReadPacket(&P, (drainmode) ? 0 : timeout,(waitfor == WAIT_DATA)) == FAIL) {
drainmode = 0;
/*
* fail if greater than %20 packets overall retries.
*/
#define ERROR_THRESHOLD (Tot_Packets < 50 || (Tot_Packets/(Tot_Retries+1)) > 4)
/*
* If we have timed out waiting for data then send a reject
*/
if (waitfor == WAIT_DATA) {
if (RxRetry && ERROR_THRESHOLD) {
--RxRetry;
/*
* sd: To properly drain on errors I found a small
* delay was needed here.
*/
Delay(15L);
++Tot_Retries;
if (debug > 7)
printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
WriteCtlPacket(CC_RJ | RxSeq);
continue;
}
}
/*
* If we have timed out waiting for an ack send the entire
* window. We must send the window sometime and it might as
* well be now.
*/
if (waitfor == WAIT_ACK) {
if (RxRetry && ERROR_THRESHOLD) {
int i;
if (debug > 7)
printf("RESEND %d packets\n", TxPend);
for (i = 1; i <= TxPend; ++i) {
Packet *p = &TxPacket[(TxSeq - TxPend + i) & 7];
p->CSeq = RxSeq;
WritePacket(p, 1);
}
--RxRetry;
++Tot_Retries;
continue;
}
}
if (debug > 7)
printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
return(FAIL);
}
/*
* valid packet, terminating condition?
*/
RxRetry = 8;
switch(P.CType) {
case CT_CONTROL:
switch(P.CCmd) {
case CC_CLOSE: /* End of communication ... not an ACK! */
if (waitfor == WAIT_CONTROL) {
*p = P;
return(SUCCESS);
}
return(FAIL);
case CC_RJ: /* Reject packet (P.CSeq == last good packet) */
(void)RecvdAck(P.CSeq);
drainmode = 1;
break;
case CC_SRJ: /* Selective Reject (P.CSeq == bad packet # ) */
return(FAIL);
case CC_RR: /* Ack to packet (P.CSeq == packet # acked) */
#ifdef NOTDEF
if (P.CSeq == ((TxSeq - TxPend) & 7)) {
/*
* The CSeq packet was previously acknowledged
* The receiver apparently has not seen anything since.
* This is the same as a rejection.
*/
goto resend;
}
#endif
if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
return(SUCCESS);
else
drainmode = 1; /* .19 */
break;
case CC_INITC:
case CC_INITB:
case CC_INITA:
if (waitfor == WAIT_CONTROL) {
*p = P;
return(SUCCESS);
}
return(FAIL);
}
break;
case CT_ALTCHN:
printf("ALTCHN packet ??\n");
break;
case CT_LONGDATA:
case CT_SHORTDATA:
{
char rxseq = P.CCmd >> 3;
char txack = P.CSeq;
if (RxRdy == 1) {
printf("Got two receive packets without me acking!\n");
}
if (rxseq == RxSeq) { /* already got this packet */
RxNotAcked = 1;
continue;
/* expected packet? */
} else if (rxseq != ((RxSeq + 1) & 7)) {
drainmode = 1;
printf("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
break;
}
if (debug > 6)
printf("RECV SEQUENCE %d\n", rxseq);
RecvdAck(txack); /* woa */
/*
* Delay sending the ACK back in case we can combine
* it with the next transmitted packet.
*/
RxNotAcked = 1; /* we haven't ack'd the rx packet */
++Tot_Packets;
RxSeq = (RxSeq + 1) & 7;
RxRdy = 1;
RxPacket = P;
if (waitfor == WAIT_DATA)
return(SUCCESS);
if (TxPend == 0 && waitfor == WAIT_ACK)
return(SUCCESS);
}
break;
}
}
}
Local
int
RecvdAck(seq)
char seq;
{
short i;
/*
* which packet was acked?
*/
for (i = 0; i < TxPend; ++i) {
if (seq == ((TxSeq - i) & 7))
break;
}
if (i && i == TxPend) {
if (seq != ((TxSeq - TxPend) & 7))
printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
return(FAIL);
}
if (debug > 7)
printf("TxPend %d -> %d\n", TxPend, i);
TxPend = i;
return(SUCCESS);
}
Local
int
WriteCtlPacket(cc)
int cc;
{
Packet pk;
pk.CType = CT_CONTROL;
pk.CCmd = cc & CC_MASK;
pk.CSeq = cc & SEQ_MASK;
pk.PLen = 0;
pk.DLen = 0;
WritePacket(&pk, 0);
return(SUCCESS);
}
Local
int
WritePacket(pk, async)
Packet *pk;
int async;
{
Frame F;
uword sum;
F.Dle = DLE;
F.C = pk->CType | pk->CCmd | pk->CSeq;
F.K = 9;
if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
F.K = LenToK(pk->DLen);
else
pk->DLen = 0;
sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
F.CH = sum >> 8;
F.CL = sum;
F.X = F.K ^ F.CH ^ F.CL ^ F.C;
if (debug > 7)
printf("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
if (async)
xwritea(&F, sizeof(F));
else
xwrite(&F, sizeof(F)); /* write header */
if (pk->DLen) { /* write data */
if (async)
xwritea(pk->Data - pk->PLen, pk->DLen);
else
xwrite(pk->Data - pk->PLen, pk->DLen);
}
return(SUCCESS);
}
Local
int
ReadPacket(pk, timeout, delay_flg)
Packet *pk;
int timeout;
int delay_flg;
{
Frame F;
short c;
short i = 0;
pk->Data = RxBuf;
pk->CType = 0xFF;
pk->CCmd = 0;
pk->CSeq = 0;
if (debug > 7)
printf("ReadPacket\n");
while ((c = xgetc(timeout,delay_flg)) != EOF) {
if (debug > 8)
printf("RP %d %02x\n", i, c);
switch(i) {
case 0:
if (c == DLE) {
F.Dle = c;
++i;
if (timeout == 0)
timeout = 1;
}
break;
case 1:
F.K = c;
++i;
if (c == DLE) { /* K only valid 1-9 */
F.Dle = c;
i = 1;
}
else if (c == 0 || c > 9)
i = 0;
break;
case 2:
F.CL = c;
++i;
break;
case 3:
F.CH = c;
++i;
break;
case 4:
F.C = c;
++i;
break;
case 5:
F.X = c;
if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
i = 0;
} else { /* get data segment if any */
++i;
}
break;
}
if (i == 6)
break;
}
if (debug > 7) {
if (i)
printf("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
else
printf("RP Hdr <rx timeout>\n");
}
if (i == 6) { /* Receive Data Portion */
uword pktsize = 1 << (F.K + 4);
uword n;
if (F.K == 9)
pktsize = 0;
if (pktsize > MaxPktSize) {
printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
return (FAIL);
}
for (n = 0; n < pktsize; ++n) {
if ((c = xgetc(4,delay_flg)) == EOF)
break;
pk->Data[n] = c;
}
if (c != EOF) {
uword hissum;
uword oursum;
hissum = (F.CH << 8) | F.CL;
oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
if (debug > 7)
printf("Got Data, checking: %04x %04x\n", hissum, oursum);
if (hissum == oursum) {
FrameToPacket(&F, pk, pk->Data);
return (SUCCESS);
}
} else {
FrameToPacket(&F, pk, pk->Data); /* mainly for pk->CType */
return (FAIL);
}
}
/*
* Timeout, retry?
*/
return (FAIL);
}
Local
int
CheckSum(s, n)
ubyte *s;
int n;
{
uword sum;
uword x;
uword t;
if (n == 0)
return(0);
sum = -1;
x = 0;
while (n) {
if (sum & 0x8000)
sum = (sum << 1) | 1;
else
sum = (sum << 1);
t = sum;
sum += *s++;
x += sum ^ n;
if (sum <= t)
sum ^= x;
--n;
}
return((int)sum);
}
Local
void
FrameToPacket(fr, pk, data)
Frame *fr;
Packet *pk;
ubyte *data;
{
pk->CType = fr->C & CT_MASK;
pk->CCmd = fr->C & CC_MASK;
pk->CSeq = fr->C & SEQ_MASK;
switch(pk->CType) {
case CT_LONGDATA:
pk->DLen = 1 << (fr->K + 4);
break;
case CT_SHORTDATA:
pk->DLen = 1 << (fr->K + 4);
if (pk->Data[0] & 0x80) {
pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
if (pk->DLen < 0) {
printf("DLEN ERROR %d\n", pk->DLen);
pk->DLen = 0;
}
pk->Data += 2;
} else {
pk->DLen -= *pk->Data;
++pk->Data;
}
break;
default:
pk->DLen = 0;
break;
}
}
Local
int
LenToK(bytes)
uword bytes;
{
uword n = 32;
uword k = 1;
while (n < bytes) {
n <<= 1;
++k;
}
if (k > 8) {
printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
k = 8;
}
return((int)k);
}