📄 httpd.c
字号:
}
/* all OK -> go to downstream state */
conn->contenttype = content_html;
/* if file is empty, handle next transfer */
if (conn->filesize == 0)
{
ht_sendStatus(conn, status_204); /* No Content */
ht_nextTransfer(conn);
return;
}
ht_sendStatus(conn, status_200); /* OK */
/* quit now if we shall only transmit the header */
if (conn->method == method_head)
{
ht_nextTransfer(conn);
return;
}
/* set up to download data */
ht_addWrSocket(conn->socket);
conn->state = STATE_DOWNSTREAM;
return;
}
/* print to the stdout of the servlet
*/
sint_t hsl_printf(SERVLET_t *slobj, const char *fmt, ...)
{
HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
sint_t len;
char b, c;
va_list args;
if (conn == NULL)
return -1;
if ((conn->state != STATE_INIT) ||
(conn->curoutbuf == NULL))
return -1;
va_start(args, fmt);
vsprintf((char*)tempbuf1_g, fmt, args);
va_end(args);
if (*tempbuf1_g == 0)
return 0;
len = 0;
b = 0;
while ((tempbuf1_g[len] != 0) || (b != 0))
{
if (conn->stdoutlen >= HTTP_SERVLETMINBUF)
{
if (conn->freeSlBufs == NULL)
break;
conn->curoutbuf->nextbuf = conn->freeSlBufs;
conn->freeSlBufs = conn->freeSlBufs->nextbuf;
conn->curoutbuf = conn->curoutbuf->nextbuf;
conn->curoutbuf->nextbuf = NULL;
conn->stdoutlen = 0;
}
if (b != 0)
{
c = b;
b = 0;
}
else
{
c = tempbuf1_g[len++];
if (c == '\n')
{
c = '\r';
b = '\n';
}
else
if (c < ' ')
continue;
}
conn->curoutbuf->buf[conn->stdoutlen++] = c;
conn->filesize++;
}
return len;
}
/* Request stream buffer memory.
*/
sint_t hsl_setStreamBufSize(SERVLET_t *slobj, u32_t bufsize)
{
HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
sint_t blocks;
if ((bufsize > maxServletMem_g) ||
(conn->state != STATE_INIT))
return SLERR_FAIL;
if (bufsize <= conn->outbufsize)
return SLERR_OK;
blocks = ((bufsize - conn->outbufsize) + (HTTP_SERVLETMINBUF - 1)) /
HTTP_SERVLETMINBUF;
conn->neededBufs = blocks;
if (ht_tryAllocateBuffers(conn) != 0)
return SLERR_NEEDMEM;
return SLERR_OK;
}
/* Create a new servlet object.
*/
sint_t hsl_create(SERVLETFUNC_t func, const char *filename)
{
char *f = (char*) filename;
SLINFO_t *si;
if (httpd_running_g == 0)
return -1;
if ((func == NULL) || (*f == 0))
return -1;
while (*f == '/') f++;
hsl_destroy(func);
si = (SLINFO_t*) sysMemAlloc(sizeof(SLINFO_t));
if (si == NULL)
return -1;
sysStrcpy(si->filename, f);
si->func = func;
SYS_MTASK_LOCK(servletLock_g);
ht_listAddHead(&servletList_g, &si->list);
SYS_MTASK_UNLOCK(servletLock_g);
return 0;
}
/* Destroy a servlet object.
*/
sint_t hsl_destroy(SERVLETFUNC_t func)
{
SLINFO_t *si;
if (httpd_running_g == 0)
return -1;
SYS_MTASK_LOCK(servletLock_g);
si = FIRST_LIST_ELEM(&servletList_g, SLINFO_t*);
while (!END_OF_LIST(&servletList_g, si))
{
if (si->func == func)
{
ht_listDel(&si->list);
sysMemFree(si);
SYS_MTASK_UNLOCK(servletLock_g);
return 0;
}
si = NEXT_LIST_ELEM(&si->list, SLINFO_t*);
}
SYS_MTASK_UNLOCK(servletLock_g);
return -1;
}
/* Get an URI parameter string by name.
*/
char *hsl_getParameterByName(SERVLET_t *slobj, const char *name)
{
HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
char *e = conn->optstring;
int l = sysStrlen(name);
while (*e != 0)
{
if (sysStrnicmp(e, name, l) == 0)
{
while ((*e != 0) && (*e != '=')) e++;
return (*e == 0) ? NULL : e + 1;
}
while (*e != 0) e++;
e++;
}
return NULL;
}
#endif /* HTTP_SERVLETS */
/*-------------------------------------------------------------------------*/
/*
#define ENABLE_LOG
#define _MYDEBUG
*/
#ifdef ENABLE_LOG
static FILE* logfile_g = NULL;
void initLog(void)
{
logfile_g = fopen("httplog.txt", "w+b");
}
void termLog(void)
{
if (logfile_g != NULL)
{
fclose(logfile_g);
logfile_g = NULL;
}
}
void log(int socket, const char *str)
{
if (socket >= 0) printf("%i: %s", socket, str);
else printf("%s", str);
if (logfile_g != NULL)
{
if (socket >= 0) fprintf(logfile_g, "%i: %s", socket, str);
else fprintf(logfile_g, "%s", str);
}
}
#else
#define log(s,x) do {} while(0)
#define initLog() do {} while(0)
#define termLog() do {} while(0)
#endif
/*-------------------------------------------------------------------------*/
/* Insert an element to the tail of a double linked list.
*/
static void ht_listAddTail(lelem_t *headelem, lelem_t *elem)
{
elem->prev = headelem->prev;
elem->next = headelem;
headelem->prev->next = elem;
headelem->prev = elem;
}
/* Insert an element to the head of a double linked list.
*/
static void ht_listAddHead(lelem_t *headelem, lelem_t *elem)
{
elem->next = headelem->next;
elem->prev = headelem;
headelem->next->prev = elem;
headelem->next = elem;
}
/* Remove an element from a double linked list
* and free its memory.
*/
static void ht_listDel(lelem_t *elem)
{
lelem_t *next = elem->next;
lelem_t *prev = elem->prev;
next->prev = prev;
prev->next = next;
INIT_LIST_HEAD(elem);
}
/*-------------------------------------------------------------------------*/
/* build a valid filename
*/
static char* ht_buildFilename(const char* uriOrFile)
{
char *f = (char*) uriOrFile;
while (*f == '/') f++;
#if !defined(HAVE_EMBEDDED_FILESYSTEM) || (FS_SUBDIRECTORIES == 0)
sysStrcpy((char*)tempbuf1_g, httpRootDir_g);
sysStrcat((char*)tempbuf1_g, f);
#ifdef DOS_PATH
for (f = (char*)tempbuf1_g; *f != 0; f++)
if (*f == '/') *f = '\\';
#endif
#else
do
{
sint_t i;
if (fsys_buildPathName((char*)tempbuf2_g, f, "") < 0)
return NULL;
i = sysStrlen((char*)tempbuf2_g);
if ((i > 0) && (tempbuf2_g[i-1] == '/')) tempbuf2_g[i-1] = 0;
if (fsys_buildPathName((char*)tempbuf1_g, httpRootDir_g,
(char*)tempbuf2_g) < 0)
return NULL;
}
while(0);
#endif
return (char*)tempbuf1_g;
}
/* read a block of data from a file
*/
static sint_t ht_readFile(HTTPCONN_t *conn, char *buf, u32_t count)
{
#if !HTTP_SERVLETS
/* handle normal file transfer */
return fsys_read(conn->filehandle, buf, count);
#else /* HTTP_SERVLETS */
u32_t c;
uint_t n;
SLBUF_t *slbuf;
if (conn->servlet == NULL)
{
/* handle normal file transfer */
return fsys_read(conn->filehandle, buf, count);
}
/* handle servlet */
if (conn->stdoutbuf == NULL)
return 0;
c = 0;
while ((c < count) && (conn->stdoutbuf != NULL))
{
n = (conn->stdoutbuf->nextbuf == NULL) ?
conn->stdoutlen : HTTP_SERVLETMINBUF;
n -= conn->outbufptr;
if (n > (uint_t) count)
n = (uint_t) count;
if (n > 0)
sysMemCopy(buf + c, conn->stdoutbuf->buf + conn->outbufptr, n);
conn->outbufptr += n;
if ((conn->outbufptr >= HTTP_SERVLETMINBUF) ||
((conn->stdoutbuf->nextbuf == NULL) &&
(conn->outbufptr >= conn->stdoutlen)))
{
conn->outbufptr = 0;
slbuf = conn->stdoutbuf;
conn->stdoutbuf = slbuf->nextbuf;
ht_freeServletBuffer(slbuf);
}
c += (u32_t) n;
}
return (sint_t) c;
#endif /* HTTP_SERVLETS */
}
/* open a file for read
*/
static sint_t ht_openFile(HTTPCONN_t *conn, sint_t mode, u32_t *size)
{
struct fsys_stat stat;
char *f;
sint_t i;
/*** test if file is a reference to a servlet ***/
#if HTTP_SERVLETS
SLINFO_t *si;
f = conn->filename;
while (*f == '/') f++;
SYS_MTASK_LOCK(servletLock_g);
si = FIRST_LIST_ELEM(&servletList_g, SLINFO_t*);
while (!END_OF_LIST(&servletList_g, si))
{
if (sysStricmp(f, si->filename) == 0)
{
/* servlet found, initialize it */
conn->servlet = si;
conn->neededBufs = 1;
SYS_MTASK_UNLOCK(servletLock_g);
return 0;
}
si = NEXT_LIST_ELEM(&si->list, SLINFO_t*);
}
SYS_MTASK_UNLOCK(servletLock_g);
#endif /* HTTP_SERVLETS */
/*** open a real file ***/
/* build initial filename:
If the client sent us just a directory name,
we try to figure out if a index.htm(l) is present. */
if (*conn->filename == 0)
{
conn->filename[0] = '/';
conn->filename[1] = 0;
}
i = sysStrlen(conn->filename);
if (conn->filename[i-1] == '/')
{
sysStrcat(conn->filename, "index.htm");
f = ht_buildFilename(conn->filename);
if (f == NULL)
{
conn->filename[i] = 0;
return -1;
}
if (fsys_stat(f, &stat) < 0)
{
sysStrcat(conn->filename, "l");
f = ht_buildFilename(conn->filename);
if (f == NULL)
{
conn->filename[i] = 0;
return -1;
}
if (fsys_stat(f, &stat) < 0)
{
conn->filename[i] = 0;
return -1;
}
}
}
else
{
f = ht_buildFilename(conn->filename);
if (fsys_stat(f, &stat) < 0)
return -1;
}
conn->filehandle = fsys_open(f, mode);
if (conn->filehandle < 0)
return -1;
*size = (u32_t) stat.st_size;
return 0;
}
/* close a file
*/
static void ht_closeFile(HTTPCONN_t *conn)
{
#if HTTP_SERVLETS
SLBUF_t *buf;
if (conn->servlet != NULL)
{
/* TODO: free all memory assigned to the servlet instance */
while (conn->stdoutbuf != NULL)
{
buf = conn->stdoutbuf;
conn->stdoutbuf = buf->nextbuf;
ht_freeServletBuffer(buf);
}
while (conn->freeSlBufs != NULL)
{
buf = conn->freeSlBufs;
conn->freeSlBufs = buf->nextbuf;
ht_freeServletBuffer(buf);
}
conn->servlet = NULL;
}
#endif
if (conn->filehandle >= 0)
{
fsys_close(conn->filehandle);
conn->filehandle = 0;
}
}
/*-------------------------------------------------------------------------*/
/* Determine and set the http content type
* of a downstram file. The content type is
* determined by evaluating the file extension.
*/
static void ht_setContentType(HTTPCONN_t *conn)
{
HTTPTYPEDEC_t *dec;
sint_t i, l;
char *f;
/* set default content type: binary (octet-stream) */
conn->contenttype = content_binary;
/* get file extension from filename */
f = conn->filename;
i = sysStrlen(f);
while ((i > 0) && (f[i-1] != '.') && (f[i-1] != '/')) i--;
if (!((i > 0) && (f[i-1] == '.')))
{
/* no extension found: unknown content, set to binary type */
return;
}
f += i;
l = 0;
while ((f[l] != 0) && (f[l] != ' ') && (f[l] != '?')) l++;
/* get content type from file-extension decoding table */
dec = contentDecodeTable;
while (*dec->extension != 0)
{
if (((sint_t)sysStrlen(dec->extension) == l) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -