⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scratchp.c

📁 嵌入式TCP/IP协议源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -