home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
stg_v4.lzh
/
stgxfr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-11
|
9KB
|
534 lines
/*
* stgxfr - version 4, third (or is it fourth?) rewrite
*
*/
#include "stgnet.h"
#include "dump.c"
#include <time.h>
#define MAX_SIZE 1024 /* max data block */
#define MAX_RECV MAX_SIZE*2
/* packet types */
#define NAK_PKT 0x00 /* request repeat of pkt */
#define ERR_PKT 0x01 /* fail request with err # */
#define RQ_INIT 0x08 /* initialize connection */
#define RP_INIT 0x09
#define RQ_PASS 0x0A /* security check */
#define RP_PASS 0x0B
#define RQ_OPEN 0x10 /* open file */
#define RP_OPEN 0x11
#define RQ_CREA 0x12 /* create file */
#define RP_CREA 0x13
#define RQ_DELE 0x14 /* delete file */
#define RP_DELE 0x15
#define RQ_RENA 0x16 /* rename file */
#define RP_RENA 0x17
#define RQ_SEEK 0x20 /* seek in file */
#define RP_SEEK 0x21
#define RQ_READ 0x22 /* read fm file */
#define RP_READ 0x23
#define RQ_WRIT 0x24 /* write to file */
#define RP_WRIT 0x25
#define RQ_CLOS 0x2E /* close file (chn 0=close connection) */
#define RP_CLOS 0x2F
#define RQ_NOP 0xFE /* no operation */
#define PKT_HDR 6 /* packet header length */
#define PKT_OVR PKT_HDR+3 /* plus crc bytes */
#define CHEK(x) ((B)(x^0xA5)) /* header check code calculation */
#ifdef _MS
#define SWAPW(x) ( ((x&0xFF00)>>8) | ((x&0x00FF)<<8) )
#define SWAPWO(x) ( ((x&0xFF00)>>8) | ((x&0x00FF)<<8) )
#else
#define SWAPW(x) (x)
#define SWAPWO(x) ( (((B*)(&x))[0]<<8) | ((B*)(&x))[1] )
#endif
struct packet
{
B type; /* packet type code */
B chek; /* header check code */
B chan; /* channel number */
B seq; /* sequence number */
W len; /* data length (+6+3=pkt len) */
B dat[MAX_SIZE+3];
};
struct Q
{
struct Q *Qnext;
struct packet *pkt;
};
struct Q *Qsend=0; /* waiting to be sent */
struct Q *Qrecv=0; /* waiting to be processed */
struct Q *Qwait=0; /* requests waiting for an answer */
struct Stat
{
long tx; /* bytes transmitted */
long rx; /* bytes received */
long lost; /* bytes receiver lost */
long sqerr; /* # of sequence errors (old seq #) */
long txerr; /* # of transmit errors */
long rxerr; /* # of receive errors */
long cycle; /* # of cyles */
} Sec,Tot;
int iTestMode=0; /* test mode flag */
int iDebug=0; /* internal debug flag */
int iMaxSend=1; /* maximum bytes to send at once */
time_t Now; /* time now */
struct packet *
NewPacket(size)
int size;
{
struct packet *new;
size+=PKT_OVR;
new=(struct packet *)malloc(size);
if (!new)
{
syslog(LOG_ERR,"malloc(%d): %m",size);
exit(errno);
}
memset((B*)new,0,size);
return(new);
}
struct Q *
AddQ(pQ,old)
struct Q **pQ;
struct Q *old;
{
struct Q *end;
if (!*pQ)
*pQ=old;
else
{
end=*pQ;
while (end->Qnext)
end=end->Qnext;
end->Qnext=old;
}
return(old);
}
struct Q *
NewQ(pQ,pkt)
struct Q **pQ;
struct packet *pkt;
{
struct Q *new;
new=(struct Q*)malloc(sizeof(*new));
if (!new)
{
syslog(LOG_ERR,"malloc(%d): %m",sizeof(*new));
exit(errno);
}
new->Qnext=0;
new->pkt=pkt;
return(AddQ(pQ,new));
}
pktcrc(buf,len,set)
B* buf;
int len,set;
{
B c[4];
c[0]=c[1]=c[2]=c[3]=0xFF;
crc(buf,len,c);
c[1]=~c[1];
c[2]=~c[2];
c[3]=~c[3];
if (set)
{
buf[len+0]=c[1];
buf[len+1]=c[2];
buf[len+2]=c[3];
return(0);
}
if
(
buf[len+0]!=c[1] ||
buf[len+1]!=c[2] ||
buf[len+2]!=c[3]
)
return(ERR);
return(0);
}
Sender()
{
static struct packet *Pnop=0; /* nop packet */
static W nopseq=0; /* nop sequence */
static struct Q *Qsending=0; /* currently sending */
static B *pcur=0; /* pointer to unsent */
static B *pend=0; /* pointer to pkt end */
int bytes;
/* if (!Qsending && !Qsend) */
if (!pcur)
{
/* nothing to do, send a nop */
if (!Pnop)
{
Pnop=NewPacket(0);
Pnop->type=RQ_NOP;
Pnop->chek=CHEK(Pnop->type);
Pnop->seq=-1;
}
Pnop->chan=(nopseq&0xFF00)>>8;
Pnop->seq=(nopseq&0x00FF);
nopseq++;
pktcrc((B*)Pnop,PKT_HDR,1);
pcur=(B*)Pnop;
pend=pcur+PKT_OVR;
}
bytes=pend-pcur;
if (bytes>iMaxSend)
bytes=iMaxSend;
if (write(1,pcur,bytes)!=bytes)
{
/* should attempt to rewind pcur to Qsending->pkt here */
Sec.txerr++;
pcur=pend=0;
}
else
{
Sec.tx+=bytes;
pcur+=bytes;
if (pcur==pend)
pcur=pend=0;
}
if (!pcur && Qsending)
{
/* free packet & queue */
free(Qsending->pkt);
free(Qsending);
Qsending=0;
}
return(0);
}
Sync(p,l)
unsigned char *p;
int l;
{
unsigned char *o=p;
if (l<2)
return(0);
l--;
while (l--)
{
if (p[1]==CHEK(p[0]))
break;
p++;
}
return(p-o);
}
Receiver()
{
static struct packet *pkt=0; /* current packet */
static int have=0; /* bytes we have in pkt */
static W nopseq=0; /* nop sequence check */
W noptmp,nopoff;
struct packet *ptr; /* movable ptr to scan pkt */
struct packet *new; /* new packet */
int bytes;
if (!pkt)
{
pkt=(struct packet *)malloc(MAX_RECV);
if (!pkt)
{
syslog(LOG_ERR,"malloc(%d): %m",MAX_RECV);
exit(errno);
}
}
bytes=_gs_rdy(0);
if (bytes==ERR)
{
return(0);
}
if (have+bytes>MAX_RECV)
bytes=MAX_RECV-have;
errno=EEOF;
if (read(0,(B*)pkt+have,bytes)!=bytes)
{
if (iDebug) wstringf(2,"read: %m\n");
Sec.rxerr++;
Sec.lost+=have;
have=0;
return(0);
}
have+=bytes;
if (iDebug)
{
wstringf(2,"Adding %d bytes, now %d:\n",bytes,have);
dump(2,pkt,have);
}
/* scan through pkt for valid packets using ptr */
ptr=pkt;
while (have>=PKT_OVR)
{
/* check header sync code */
if (ptr->chek!=CHEK(ptr->type))
{
bytes=Sync((B*)ptr,have);
if (iDebug) wstringf(2,"Throwing out %d bytes\n",bytes);
Sec.lost+=bytes;
((B*)ptr)+=bytes;
have-=bytes;
continue;
}
/* is the size kosher? */
bytes=SWAPWO(ptr->len);
if (bytes>MAX_SIZE)
{
if (iDebug) wstringf(2,"Impossible length value: %d\n",bytes);
ptr->type++;
continue;
}
/* do we have the entire packet? */
bytes+=PKT_OVR;
if (bytes>have)
{
break;
}
/* is the crc correct? */
if (pktcrc((B*)ptr,bytes-3,0))
{
if (iDebug) wstringf(2,"Bad CRC\n");
ptr->type++;
continue;
}
/* is it a nop packet? */
if (ptr->type==RQ_NOP)
{
noptmp=(ptr->chan<<8)|ptr->seq;
if (noptmp!=nopseq)
{
/*wstringf(2,"[%04X-%04X]",nopseq,noptmp);*/
nopoff=noptmp-nopseq;
if (nopoff>=0x8000)
{
if (iDebug) wstringf(2,"Packet out of sequence: %04X (current=%04X)\n",
noptmp,nopseq);
Sec.sqerr++;
}
else
{
Sec.lost+=PKT_OVR*nopoff;
nopoff=noptmp-1;
nopseq=noptmp;
if (iDebug) wstringf(2,"Lost packets: %04X - %04X\n",nopseq,nopoff);
}
Sec.rx+=bytes;
}
else
{
/* write(2,".",1); */
Sec.rx+=bytes;
}
nopseq++;
/* throw it away */
if (iDebug) wstringf(2,"Nop Packet: skipping %d bytes\n",bytes);
((B*)ptr)+=bytes;
have-=bytes;
continue;
}
/* put packet on queue */
new=NewPacket(bytes);
memcpy((B*)new,(B*)ptr,bytes);
AddQ(&Qrecv,new);
if (iDebug) wstringf(2,"Other Packet: skipping %d bytes\n",bytes);
Sec.rx+=bytes;
((B*)ptr)+=bytes;
have-=bytes;
}
if (iDebug)
{
wstringf(2,"Left is %d bytes:\n",have);
dump(2,ptr,have);
}
/* move remainder (ptr through pkt+have) back to beginning of pkt */
if (ptr!=pkt)
memcpy((B*)pkt,(B*)ptr,have);
return(0);
}
Second()
{
int baud;
int perf;
if (Sec.rx)
if (Sec.lost+Sec.sqerr)
{
/* are receiving bytes, but have lost some */
if (iMaxSend>1)
{
iMaxSend--;
if (iTestMode)
wstringf(2,"MaxSend now %d\n",iMaxSend);
}
}
else
{
/* no loss, increase it */
iMaxSend++;
if (iTestMode)
wstringf(2,"MaxSend now %d\n",iMaxSend);
}
if (iTestMode)
{
baud=(Sec.tx+Sec.rx)*10;
if ((Sec.lost+Sec.sqerr) && Sec.rx)
perf=100*Sec.rx/(Sec.rx+Sec.lost+Sec.sqerr*PKT_OVR);
else if (Sec.rx)
perf=100;
else
perf=0;
wstringf(2,"T=%5d R=%5d L=%5d S=%5d E=%5d C=%5d B=%5d P=%3d%%\n",
Sec.tx,
Sec.rx,
Sec.lost,
Sec.sqerr,
Sec.txerr+Sec.rxerr,
Sec.cycle,
baud,
perf);
}
memset(&Sec,0,sizeof(Sec));
}
Running()
{
static time_t Last;
Now=time(0);
if (Now!=Last)
{
Second();
Last=Now;
}
Sec.cycle++;
Sender();
Receiver();
return(1);
}
TestMode()
{
struct Q *Qtemp;
iTestMode=1;
wstringf(2,"TEST MODE\n");
if (isatty(0))
_ss_mode(0,-1);
if (isatty(1))
_ss_mode(1,-1);
while (Running())
{
if (Qrecv)
{
wstringf(2,"recv: %02X %02X %02X %04X\n",
Qrecv->pkt->type,
Qrecv->pkt->chan,
Qrecv->pkt->seq,
SWAPW(Qrecv->pkt->len));
Qtemp=Qrecv;
Qrecv=Qrecv->Qnext;
free(Qtemp->pkt);
free(Qtemp);
}
}
}
void
Help()
{
wstringf(1,"stgxfr - StG-Net Transfer Protocol\n");
wstringf(1," ** FOR INTERNAL USE ONLY **\n");
STGVER;
exit(1);
}
void
main(argc,argv)
char **argv;
{
openlog(*argv,0,LOG_STGNET);
dash(argv)
{
case '#':
wstringf(2,"stgxfr: %s\n",STG_VER);
exit(0);
case 'd': iDebug++; break;
case 't': TestMode();
case '?':
default:
Help();
}
}