📄 scratchp.c
字号:
BYTE rxflags=0, *p;
SCRATCHPKT *sp;
sp = getframe_datap(nfp); /* Get pointer to frame data */
if (rxlen) /* If packet received.. */
{
rxflags = sp->h.flags; /* Decode command & data areas */
if (rxflags&FLAG_CMD || rxflags&FLAG_RESP)
crlen = strlen((char *)sp->data) + 1;
dlen = sp->h.dlen - crlen; /* Actual data is after command */
diaghdrs[diagidx] = sp->h; /* Store hdr in diagnostic log */
diaghdrs[diagidx].ver = DIAG_RX;
diagidx = (diagidx + 1) % NDIAGS;
if (rxflags & FLAG_ERR) /* Convert flags into signals */
sig = SIG_ERR;
else if (rxflags & FLAG_STOP)
sig = SIG_STOP;
else if (rxflags & FLAG_CMD)
sig = SIG_CMD;
else if (rxflags & FLAG_RESP)
sig = SIG_RESP;
else if (rxflags & FLAG_START)
sig = SIG_START;
else if (rxflags & FLAG_CONN)
sig = SIG_CONN;
}
if (sigdebug && sig && sig!=SIG_CONN && sig<USER_SIGS)
printf("Signal %s ", signames[sig]);
if (connstate == STATE_IDLE) /* If idle state.. */
{
timeout(&errtimer, 0); /* Refresh timer */
switch (sig) /* Check signals */
{
case SIG_USER_IDENT: /* User IDENT request? */
txlen = make_scratchpds(nfp, bcast, CMD_IDENT, FLAG_CMD, "");
break;
case SIG_USER_OPEN: /* User OPEN request? */
txlen = make_scratchpds(nfp, bcast, CMD_IDENT, FLAG_CMD, remid);
buff_setall(&txbuff, 1); /* My distinctive SEQ value */
newconnstate(STATE_IDENT); /* Start ident cycle */
break;
case SIG_CMD: /* Command signal? */
if (!strcmp((char *)sp->data, CMD_IDENT))
{ /* IDENT cmd with my ID or null? */
if (dlen<2 || !strncmp((char *)&sp->data[crlen], locid, dlen))
{ /* Respond to sender */
txlen = make_scratchp(nfp, getframe_srcep(nfp), CMD_IDENT,
FLAG_RESP, locid, strlen(locid)+1);
}
}
break;
case SIG_RESP: /* Response signal? */
if (!strcmp((char *)sp->data, CMD_IDENT))
{ /* IDENT response? */
printf("Ident '%s'", (char *)&sp->data[crlen]);
if ((p=getframe_srcep(nfp)) !=0 )
printf(" address %s", ethstr(p, temps));
printf("\n");
}
break;
case SIG_START: /* START signal? */
getframe_srce(nfp, remaddr);
buff_setall(&txbuff, 0x8001); /* My distinctive SEQ value */
txack = sp->h.seq; /* My ack is his SEQ */
buff_setall(&rxbuff, txack);
*remid = 0; /* Clear remote ID */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_CONN, 0, 0);
newconnstate(STATE_CONNECTED); /* Go connected */
break;
case SIG_CONN: /* CONNECTED or STOP signal? */
case SIG_STOP:
txlen = make_scratchp(nfp, getframe_srcep(nfp), 0, FLAG_ERR, 0, 0);
break; /* Send error */
}
}
else if (connstate == STATE_IDENT) /* If in identification cycle.. */
{
switch (sig) /* Check signals */
{
case SIG_RESP: /* Got IDENT response? */
if (!strcmp((char *)sp->data, CMD_IDENT) && dlen<=IDLEN)
{
if (!remid[0] || !strcmp((char *)&sp->data[crlen], remid))
{ /* Get remote addr and ID */
getframe_srce(nfp, remaddr);
strcpy(remid, (char *)&sp->data[crlen]);
txlen = make_scratchp(nfp, remaddr, 0, FLAG_START, 0, 0);
newconnstate(STATE_OPEN);
} /* Open up the connection */
}
break;
case SIG_ERR: /* Error response? */
newconnstate(STATE_IDLE); /* Go idle */
break;
case SIG_TIMEOUT: /* Timeout on response? */
n = strlen(remid) + 1; /* Resend IDENT command */
txlen = make_scratchp(nfp, bcast, CMD_IDENT, FLAG_CMD, remid, n);
break;
case SIG_FAIL: /* Failed? */
newconnstate(STATE_IDLE); /* Go idle */
break;
}
}
else if (connstate == STATE_OPEN) /* If I requested a connection.. */
{
switch (sig) /* Check signals */
{
case SIG_START:
case SIG_CONN: /* Response OK? */
buff_setall(&rxbuff, sp->h.seq);
txlen = make_scratchp(nfp, remaddr, 0, FLAG_CONN, 0, 0);
newconnstate(STATE_CONNECTED); /* Send connect, go connected */
break;
case SIG_STOP: /* Stop already? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_STOP, 0, 0);
newconnstate(STATE_IDLE); /* Send stop, go idle */
break;
case SIG_ERR: /* Error response? */
newconnstate(STATE_IDLE);
break; /* Go idle */
case SIG_TIMEOUT: /* Timeout on response? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_START, 0, 0);
break; /* Resend request */
case SIG_FAIL: /* Failed? */
newconnstate(STATE_IDLE); /* Go idle */
break;
}
}
else if (connstate == STATE_CONNECTED) /* If connected.. */
{
switch (sig) /* Check signals */
{
case SIG_START: /* Duplicate START? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_CONN, 0, 0);
break; /* Still connected */
case SIG_TIMEOUT: /* Timeout on acknowledge? */
buff_retry(&txbuff, buff_trylen(&txbuff));
/* Rewind data O/P buffer */
/* Fall through to normal connect.. */
case SIG_CONN: /* If newly connected.. */
case SIG_NULL: /* ..or still connected.. */
/* Check received packet */
if (rxlen > 0) /* Received packet? */
{
newconnstate(connstate); /* Refresh timeout timer */
/* Rx seq shows how much of his data he thinks I've received */
oldrx = rxbuff.in - sp->h.seq; /* Check for his repeat data */
if (oldrx == 0) /* Accept up-to-date data */
buff_in(&rxbuff, &sp->data[crlen], dlen);
else if (oldrx <= WINDOWSIZE) /* Respond to repeat data.. */
tx = 1; /* ..with forced (repeat) ack */
else /* Reject out-of-window data */
errstr = "invalid SEQ";
/* Rx ack shows how much of my data he's actually received */
acked = sp->h.ack - txbuff.out; /* Check amount acked */
if (acked <= buff_trylen(&txbuff))
buff_out(&txbuff, 0, (WORD)acked); /* My Tx data acked */
else
errstr = "invalid ACK";
rxw = rxbuff.in - txack; /* Check Rx window.. */
if (rxw >= WINDOWSIZE/2) /* ..force Tx ack if 1/2 full */
tx = 1;
if (errstr) /* If error, close connection */
{
printf("Protocol error: %s\n", errstr);
txlen = make_scratchp(nfp, remaddr, 0, FLAG_ERR, 0, 0);
newconnstate(STATE_IDLE);
}
}
/* Check whether a transmission is needed */
txw = WINDOWSIZE - buff_trylen(&txbuff);/* Check Tx window space */
trylen = minw(buff_untriedlen(&txbuff), /* ..size of data avail */
minw(SCRATCHPDLEN, txw)); /* ..and max packet len */
if (trylen>0 || sig==SIG_TIMEOUT || tx) /* If >0, or timeout.. */
{ /* ..or forced Tx.. */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_CONN, 0, trylen);
buff_try(&txbuff, sp->data, trylen);/* ..do a transmission */
txack = rxbuff.in;
}
if (buff_trylen(&txbuff) == 0) /* If all data acked.. */
newconnstate(connstate); /* refresh timer (so no timeout) */
break;
case SIG_USER_CLOSE: /* User closing connection? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_STOP, 0, 0);
newconnstate(STATE_CLOSE); /* Send stop command, go close */
break;
case SIG_STOP: /* STOP command? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_STOP, 0, 0);
newconnstate(STATE_IDLE); /* Send ack, go idle */
break;
case SIG_ERR: /* Error command? */
newconnstate(STATE_IDLE); /* Go idle */
break;
case SIG_FAIL: /* Application failed? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_ERR, 0, 0);
newconnstate(STATE_IDLE); /* Send stop command, go idle */
break;
}
}
else if (connstate == STATE_CLOSE) /* If I'm closing connection.. */
{
switch (sig) /* Check signals */
{
case SIG_STOP: /* Stop or error command? */
case SIG_ERR:
newconnstate(STATE_IDLE); /* Go idle */
break;
case SIG_TIMEOUT: /* Timeout on response? */
txlen = make_scratchp(nfp, remaddr, 0, FLAG_STOP, 0, 0);
break; /* Resend stop command */
}
}
return(txlen);
}
/* Do application-specific tasks, given I/P and O/P buffers, and command string
** Return a connection signal value, 0 if no signal */
int do_apps(CBUFF *rxb, CBUFF *txb, int usersig)
{
WORD len;
BYTE lenb;
int connsig=0;
char cmd[CMDLEN+1];
if (sigdebug && usersig && usersig>=USER_SIGS)
printf("Signal %s ", signames[usersig]);
connsig = usersig; /* Send signal to connection */
if (connstate != STATE_CONNECTED) /* If not connected.. */
; /* Do nothing! */
else if (appstate == APP_IDLE) /* If application is idle.. */
{
if (usersig == SIG_USER_DIR) /* User requested directory? */
{ /* Send command */
buff_in(txb, (BYTE *)CMD_DIR, sizeof(CMD_DIR));
}
else if (usersig == SIG_USER_GET) /* User 'GET' command? */
{
filelen = 0; /* Open file */
if ((fhandle = fopen(filename, "wb"))==0)
printf("Can't open file\n");
else
{ /* Send command & name to remote */
buff_instr(txb, CMD_GET " ");
buff_in(txb, (BYTE *)filename, (WORD)(strlen(filename)+1));
newappstate(APP_FILE_RECEIVER); /* Become receiver */
}
}
else if (usersig == SIG_USER_PUT) /* User 'PUT' command? */
{
filelen = 0; /* Open file */
if ((fhandle = fopen(filename, "rb"))==0)
printf("Can't open file\n");
else
{ /* Send command & name to remote */
buff_instr(txb, CMD_PUT " ");
buff_in(txb, (BYTE *)filename, (WORD)(strlen(filename)+1));
newappstate(APP_FILE_SENDER); /* Become sender */
}
}
else if (usersig == SIG_USER_ECHO) /* User equested echo? */
{
buff_in(txb, (BYTE *)CMD_ECHO, sizeof(CMD_ECHO));
txoff = rxoff = 0; /* Send echo command */
newappstate(APP_ECHO_CLIENT); /* Become echo client */
}
else if ((len=buff_strlen(rxb))>0 && len<=CMDLEN)
{
len++; /* Possible command string? */
buff_out(rxb, (BYTE *)cmd, len);
if (!strcmp(cmd, CMD_ECHO)) /* Echo command? */
newappstate(APP_ECHO_SERVER); /* Become echo server */
else if (!strcmp(cmd, CMD_DIR)) /* DIR command? */
do_dir(txb); /* Send DIR O/P to buffer */
else if (!strncmp(cmd, CMD_GET, 3)) /* GET command? */
{ /* Try to open file */
filelen = 0;
strcpy(filename, &cmd[4]);
if ((fhandle = fopen(filename, "rb"))!=0)
newappstate(APP_FILE_SENDER); /* If OK, become sender */
else /* If not, respond with null */
buff_in(txb, (BYTE *)"\0", 1);
}
else if (!strncmp(cmd, CMD_PUT, 3)) /* PUT command? */
{
filelen = 0;
strcpy(filename, &cmd[4]); /* Try to open file */
fhandle = fopen(filename, "wb");
newappstate(APP_FILE_RECEIVER); /* Become receiver */
}
}
else /* Default: show data from remote */
{
len = buff_out(rxb, apptemp, TESTLEN);
apptemp[len] = 0;
printf("%s", apptemp);
}
}
else if (appstate == APP_ECHO_CLIENT) /* If I'm an echo client.. */
{
if (usersig==SIG_USER_CLOSE) /* User closing connection? */
newappstate(APP_IDLE);
else
{ /* Generate echo data.. */
if ((len = minw(buff_freelen(txb), TESTLEN)) > TESTLEN/2)
{
len = rand() % len; /* ..random data length */
buff_in(&txbuff, &testdata[txoff], len);
txoff = (txoff + len) % TESTLEN;/* ..move & wrap data pointer */
}
if ((len = buff_out(rxb, apptemp, TESTLEN)) > 0)
{ /* Check response data */
if (!memcmp(apptemp, &testdata[rxoff], len))
{ /* ..match with data buffer */
rxoff = (rxoff + len) % TESTLEN;/* ..move & wrap data ptr */
testlen += len;
printf("%lu bytes OK \r", testlen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -