📄 webserve.c
字号:
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 + -