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

📄 webserve.c

📁 一个功能精简的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
        ok = 0;
    else if (conn == TCP_OPEN)
    {
        adp->in = 0;
    }
    else if (conn == TCP_DATA)
    {
        if ((len = buff_chrlen(&ts->rxb, '\n'))!=0) /* Got request? */
        {
            len = mini(len+1, HTTP_MAXLEN);         /* Truncate length */
            buff_out(&ts->rxb, (BYTE *)httpreq, (WORD)len);
            httpreq[len] = 0;
            if (webdebug)                           /* Display if debugging */
                printf("%s", httpreq);
            s = strtok(httpreq, " ");               /* Chop into tokens */
            if (!strcmp(s, "GET"))                  /* 1st token is 'GET'? */
            {
                name = strtok(0, " ?\r\n");         /* 2nd token is filename */
                http_get(ts, name);                 /* Process filename */
            }
        }
    }
    http_data(ts);
    return(ok);
}

/* Process the filepath from an HTTP 'get' method */
void http_get(TSOCK *ts, char *fname)
{
    APPDATA *adp;
    char *s=0;

    adp = (APPDATA *)ts->app;
    strcpy(filepath, filedir);          /* Add on base directory */
    if (*fname)                         /* Copy filename without leading '/' */
        strcat(filepath, fname+1);      
    strlwr(filepath);                   /* Force to lower-case */
    if (strlen(fname) <= 1)
    {                                   /* If name is only a '/'.. */
        if (webdebug)                   /* Display if debugging */
            printf("Sending directory\n", filepath);
        strcpy(filepath, filedir);
        strcat(filepath, "*.*");        /* ..display directory */
#if HTML_DIR == 3
        dir_head(&ts->txb, filedir);    /* Send out directory */
        adp->count = 1;
#elif HTML_DIR > 0
        dir_head(&ts->txb, filedir);    /* Send out directory */
        if ((s = find_first(filepath)) != 0) do {
            dir_entry(&ts->txb, s);
        } while ((s = find_next()) != 0);
        dir_tail(&ts->txb);
        close_tcp(ts);
#else
        buff_instr(&ts->txb, HTTP_OK HTTP_TXT HTTP_BLANK);
        buff_instr(&ts->txb, "Directory\r\n");
        if ((s = find_first(filepath)) != 0) do {
            buff_instr(&ts->txb, s);    /* One file per line */
            buff_instr(&ts->txb, "\r\n");
        } while ((s = find_next()) != 0);
        close_tcp(ts);
#endif
    }                                   /* If file not found.. */
    else if ((adp->in = fopen(filepath, "rb")) == 0)
    {                                   /* ..send message */
        if (webdebug)                   /* Display if debugging */
            printf("File '%s' not found\n", filepath);
        buff_instr(&ts->txb, HTTP_NOFILE HTTP_TXT HTTP_BLANK);
        buff_inprintf(&ts->txb, "Webserve v%s\r\n", VERSION);
        buff_inprintf(&ts->txb, "Can't find '%s'\r\n", filepath);
        close_tcp(ts);
    }
    else                                /* File found OK */
    {
#if HTTP_HEAD == 0
                                                    /* No HTTP header or.. */
#elif HTTP_HEAD == 1                                /* Simple OK header or.. */
        buff_instr(&ts->txb, HTTP_OK HTTP_BLANK);
#else                                               /* Content-type header */
        buff_instr(&ts->txb, HTTP_OK);
        s = strstr(filepath, ".htm") ? HTTP_HTM :
            strstr(filepath, ".txt") ? HTTP_TXT :
            strstr(filepath, ".gif") ? HTTP_GIF :
            strstr(filepath, ".xbm") ? HTTP_XBM : "";
        buff_instr(&ts->txb, s);
        buff_instr(&ts->txb, HTTP_BLANK);
#endif
        if (webdebug)                   /* Display if debugging */
            printf("File '%s' %s", filepath, *s ? s : "\n");
    }
}

/* If there is space in the transmit buffer, send HTTP data */
void http_data(TSOCK *ts)
{
    APPDATA *adp;
    int count=0, ok, len;
    char *s;

    adp = (APPDATA *)ts->app;
    if (adp->count)                     /* If sending a directory.. */
    {                                   /* Skip filenames already sent */
        ok = (s = find_first(filepath)) != 0;
        while (ok && ++count<adp->count)
            ok = (s = find_next()) != 0;
        while (ok && dir_entry(&ts->txb, s))
        {                               /* Send as many entries as will fit */
            adp->count++;
            ok = (s = find_next()) != 0;
        }
        if (!ok && dir_tail(&ts->txb))  /* If no more entries.. */
        {
            adp->count = 0;             /* ..start closing connection */
            close_tcp(ts);
        }
    }                                   /* If sending a file.. */
    if (adp->in && (len = buff_freelen(&ts->txb)) > 0)
    {                                   /* ..put out as much as possible */
        if ((len = buff_infile(&ts->txb, adp->in, (WORD)len)) == 0)
        {                               /* If end of file, close it.. */
            fclose(adp->in);
            adp->in = 0;
            close_tcp(ts);              /* ..and start closing connection */
        }
    }
}

/* Write out head of HTML file dir, given filepath. Return 0 if error */
int dir_head(CBUFF *bp, char *path)
{
#if HTML_DIR > 1
    return(buff_instr(bp, HTTP_OK HTTP_HTM HTTP_BLANK) &&
           buff_instr(bp, "<html><head><title>Directory</title></head>\r\n") &&
           buff_inprintf(bp, "<body><h2>Directory of %s</h2>\r\n", path) &&
           buff_instr(bp, "<table><th>File</th><th>Size</th>\r\n"));
#else
    return(buff_instr(bp, HTTP_OK HTTP_HTM HTTP_BLANK) &&
           buff_instr(bp, "<html><head><title>Directory</title></head>\r\n") &&
           buff_inprintf(bp, "<body><h2>Directory of %s</h2>\r\n", path));
#endif
}

/* Write out HTML file dir entry, given name. Return 0 if buffer full */
int dir_entry(CBUFF *bp, char *name)
{
#if HTML_DIR > 1
    return(buff_inprintf(bp, "<tr><td><a href='%s'>%s</a></td>", name, name) &&
           buff_inprintf(bp, "<td>%lu</td></tr>\r\n", find_filesize()));
#else
    return(buff_inprintf(bp, "<a href='%s'>%s</a><br>\r\n", name, name));
#endif
}

/* Write out tail of HTML file dir. Return length, 0 if error */
int dir_tail(CBUFF *bp)
{
#if HTML_DIR > 1
    return(buff_instr(bp, "</table></body></html>\r\n"));
#else
    return(buff_instr(bp, "</body></html>\r\n"));
#endif
}

/* Check for incoming packets, send response if required */
void do_receive(GENFRAME *gfp)
{
    NODE node;
    ARPKT *arp;
    IPKT *ip;
    ICMPKT *icmp;
    int rxlen, txlen, len;

    if ((rxlen=get_frame(gfp)) > 0)                 /* Any incoming frames? */
    {
        ip = getframe_datap(gfp);
        if (is_arp(gfp, rxlen))
        {                                           /* ARP response? */
            arp = getframe_datap(gfp);
            if (arp->op==ARPREQ && arp->dip==locnode.ip)
            {                                       /* ARP request? */
                node.ip = arp->sip;                 /* Make ARP response */
                memcpy(node.mac, arp->smac, MACLEN);
                txlen = make_arp(gfp, &locnode, &node, ARPRESP);
                put_frame(gfp, txlen);              /* Send packet */
            }
            if (arp->op==ARPRESP && arp->dip==locnode.ip)
            {                                       /* ARP response? */
                arp_receive(tsocks, NSOCKS, gfp);
            }
        }
        else if ((rxlen=is_ip(gfp, rxlen))!=0 &&    /* IP datagram? */
                 ip->i.dip==locnode.ip || ip->i.dip==BCASTIP)
        {
            getip_srce(gfp, &node);
            if ((len=is_icmp(ip, rxlen))!=0)        /* ICMP? */
            {
                icmp = (ICMPKT *)ip;
                if (icmp->c.type==ICREQ)            /* Echo request? */
                {
                    len = (WORD)maxi(len, 0);       /* Make response */
                    txlen = make_icmp(gfp, &locnode, &node, ICREP,
                                      icmp->c.code, (WORD)len);
                    put_frame(gfp, txlen);          /* Send packet */
                }
            }
            else if ((len=is_tcp(ip, rxlen))!=0)    /* TCP? */
            {
                tcp_receive(tsocks, NSOCKS, gfp, len);
            }
        }
    }
}

/* Poll the network interface to keep it alive */
void do_poll(GENFRAME *gfp)
{
    tcp_poll(tsocks, NSOCKS, gfp);
    poll_net(gfp->g.dtype);
}

/* Version of printf() to write a string into a circular buffer.
** Return string length, or zero if insufficient room in buffer */
int buff_inprintf(CBUFF *bp, char *str, ...)
{
    char temps[200];
    int len;

    va_list argptr;
    va_start(argptr, str);
    len = vsprintf(temps, str, argptr);
    va_end(argptr);
    if (len<=0 || len>buff_freelen(bp))
        len = 0;
    else
        buff_in(bp, (BYTE *)temps, (WORD)len);
    return(len);
}

/* Display usage help */
void disp_usage(void)
{
    printf("Usage:    WEBSERVE [ options ] [ directory ]\n");
    printf("          If no directory specified, default is '%s'\n", FILEDIR);
    printf("Options:  -c name   Config filename (default %s)\n", CFGFILE);
    printf("          -s        State display\n");
    printf("          -t        TCP segment display\n");
    printf("          -v        Verbose packet display\n");
    printf("          -w        Web (HTTP) diagnostics\n");
    printf("          -x        Hex packet display\n");
    printf("Example:  WEBSERVE c:\\mydocs\n");
}

/* Ctrl-break handler: set flag and return */
void break_handler(int sig)
{
    breakflag = sig;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -