📄 webs.c
字号:
return r;
}
/******************************************************************************/
/*
* Decode a URL (or part thereof). Allows insitu decoding.
*/
void websDecodeUrl(char_t *decoded, char_t *token, int len)
{
char_t *ip, *op;
int num, i, c;
a_assert(decoded);
a_assert(token);
op = decoded;
for (ip = token; *ip && len > 0; ip++, op++) {
if (*ip == '+') {
*op = ' ';
} else if (*ip == '%' && gisxdigit(ip[1]) && gisxdigit(ip[2])) {
/*
* Convert %nn to a single character
*/
ip++;
for (i = 0, num = 0; i < 2; i++, ip++) {
c = tolower(*ip);
if (c >= 'a' && c <= 'f') {
num = (num * 16) + 10 + c - 'a';
} else {
num = (num * 16) + c - '0';
}
}
*op = (char_t) num;
ip--;
} else {
*op = *ip;
}
len--;
}
*op = '\0';
}
/******************************************************************************/
#ifdef WEBS_LOG_SUPPORT
/*
* Output a log message
*/
static void websLog(webs_t wp, int code)
{
char_t *buf;
char *abuf;
int len;
#define qAnlLog 1
#ifdef qAnlLog
time_t timer;
char_t* newLine = NULL;
char_t* timeStr = NULL;
#endif
a_assert(websValid(wp));
buf = NULL;
#ifdef qAnlLog
time(&timer);
timeStr = ctime(&timer);
newLine = gstrchr(timeStr, '\n');
if (newLine)
{
*newLine = '\0';
}
fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%s\t%s\t%s\tcode = %d\n"),
timeStr, wp->ipaddr, wp->url, code);
#else
fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%d %s %d %d\n"), time(0),
wp->url, code, wp->written);
#endif
len = gstrlen(buf);
abuf = ballocUniToAsc(buf, len+1);
write(websLogFd, abuf, len);
bfreeSafe(B_L, buf);
bfreeSafe(B_L, abuf);
}
#endif /* WEBS_LOG_SUPPORT */
/******************************************************************************/
/*
* Request timeout. The timeout triggers if we have not read any data from
* the users browser in the last WEBS_TIMEOUT period. If we have heard from
* the browser, simply re-issue the timeout.
*/
void websTimeout(void *arg, int id)
{
webs_t wp;
int delay, tm;
wp = (webs_t) arg;
a_assert(websValid(wp));
tm = websGetTimeSinceMark(wp) * 1000;
if (tm >= WEBS_TIMEOUT) {
websStats.timeouts++;
emfUnschedCallback(id);
/*
* Clear the timeout id
*/
wp->timeout = -1;
websDone(wp, 404);
} else {
delay = WEBS_TIMEOUT - tm;
a_assert(delay > 0);
emfReschedCallback(id, delay);
}
}
/******************************************************************************/
/*
* Called when the request is done.
*/
void websDone(webs_t wp, int code)
{
a_assert(websValid(wp));
/*
* Disable socket handler in case keep alive set.
*/
socketDeleteHandler(wp->sid);
if (code != 200) {
wp->flags &= ~WEBS_KEEP_ALIVE;
}
#ifdef WEBS_PROXY_SUPPORT
if (! (wp->flags & WEBS_LOCAL_PAGE)) {
websStats.activeNetRequests--;
}
#endif
#ifdef WEBS_LOG_SUPPORT
if (! (wp->flags & WEBS_REQUEST_DONE)) {
websLog(wp, code);
}
#endif
/*
* Close any opened document by a handler
*/
websPageClose(wp);
/*
* Exit if secure.
*/
#ifdef WEBS_SSL_SUPPORT
if (wp->flags & WEBS_SECURE) {
websTimeoutCancel(wp);
websSSLFlush(wp->wsp);
socketCloseConnection(wp->sid);
websFree(wp);
return;
}
#endif
/*
* If using Keep Alive (HTTP/1.1) we keep the socket open for a period
* while waiting for another request on the socket.
*/
if (wp->flags & WEBS_KEEP_ALIVE) {
if (socketFlush(wp->sid) == 0) {
wp->state = WEBS_BEGIN;
wp->flags |= WEBS_REQUEST_DONE;
if (wp->header.buf) {
ringqFlush(&wp->header);
}
socketCreateHandler(wp->sid, SOCKET_READABLE, websSocketEvent,
(int) wp);
websTimeoutCancel(wp);
wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout,
(void *) wp);
return;
}
} else {
websTimeoutCancel(wp);
socketSetBlock(wp->sid, 1);
socketFlush(wp->sid);
socketCloseConnection(wp->sid);
}
websFree(wp);
}
/******************************************************************************/
/*
* Allocate a new webs structure
*/
int websAlloc(int sid)
{
webs_t wp;
int wid;
/*
* Allocate a new handle for this connection
*/
if ((wid = hAllocEntry((void***) &webs, &websMax,
sizeof(struct websRec))) < 0) {
return -1;
}
wp = webs[wid];
wp->wid = wid;
wp->sid = sid;
wp->state = WEBS_BEGIN;
wp->docfd = -1;
wp->timeout = -1;
wp->dir = NULL;
wp->authType = NULL;
wp->protocol = NULL;
wp->protoVersion = NULL;
wp->password = NULL;
wp->userName = NULL;
#ifdef DIGEST_ACCESS_SUPPORT
wp->realm = NULL;
wp->nonce = NULL;
wp->digest = NULL;
wp->uri = NULL;
wp->opaque = NULL;
wp->nc = NULL;
wp->cnonce = NULL;
wp->qop = NULL;
#endif
#ifdef WEBS_SSL_SUPPORT
wp->wsp = NULL;
#endif
ringqOpen(&wp->header, WEBS_HEADER_BUFINC, WEBS_MAX_HEADER);
/*
* Create storage for the CGI variables. We supply the symbol tables for
* both the CGI variables and for the global functions. The function table
* is common to all webs instances (ie. all browsers)
*/
wp->cgiVars = symOpen(WEBS_SYM_INIT);
return wid;
}
/******************************************************************************/
/*
* Free a webs structure
*/
void websFree(webs_t wp)
{
a_assert(websValid(wp));
if (wp->path)
bfree(B_L, wp->path);
if (wp->url)
bfree(B_L, wp->url);
if (wp->host)
bfree(B_L, wp->host);
if (wp->lpath)
bfree(B_L, wp->lpath);
if (wp->query)
bfree(B_L, wp->query);
if (wp->decodedQuery)
bfree(B_L, wp->decodedQuery);
if (wp->authType)
bfree(B_L, wp->authType);
if (wp->password)
bfree(B_L, wp->password);
if (wp->userName)
bfree(B_L, wp->userName);
if (wp->cookie)
bfree(B_L, wp->cookie);
if (wp->userAgent)
bfree(B_L, wp->userAgent);
if (wp->dir)
bfree(B_L, wp->dir);
if (wp->protocol)
bfree(B_L, wp->protocol);
if (wp->protoVersion)
bfree(B_L, wp->protoVersion);
if (wp->cgiStdin)
bfree(B_L, wp->cgiStdin);
#ifdef DIGEST_ACCESS_SUPPORT
if (wp->realm)
bfree(B_L, wp->realm);
if (wp->uri)
bfree(B_L, wp->uri);
if (wp->digest)
bfree(B_L, wp->digest);
if (wp->opaque)
bfree(B_L, wp->opaque);
if (wp->nonce)
bfree(B_L, wp->nonce);
if (wp->nc)
bfree(B_L, wp->nc);
if (wp->cnonce)
bfree(B_L, wp->cnonce);
if (wp->qop)
bfree(B_L, wp->qop);
#endif
#ifdef WEBS_SSL_SUPPORT
websSSLFree(wp->wsp);
#endif
symClose(wp->cgiVars);
if (wp->header.buf) {
ringqClose(&wp->header);
}
websMax = hFree((void***) &webs, wp->wid);
bfree(B_L, wp);
a_assert(websMax >= 0);
}
/******************************************************************************/
/*
* Return the server address
*/
char_t *websGetHost()
{
return websHost;
}
/******************************************************************************/
/*
* Return the the url to access the server. (ip address)
*/
char_t *websGetIpaddrUrl()
{
return websIpaddrUrl;
}
/******************************************************************************/
/*
* Return the server address
*/
char_t *websGetHostUrl()
{
return websHostUrl;
}
/******************************************************************************/
/*
* Return the listen port
*/
int websGetPort()
{
return websPort;
}
/******************************************************************************/
/*
* Get the number of bytes to write
*/
int websGetRequestBytes(webs_t wp)
{
a_assert(websValid(wp));
return wp->numbytes;
}
/******************************************************************************/
/*
* Get the directory for this request
*/
char_t *websGetRequestDir(webs_t wp)
{
a_assert(websValid(wp));
if (wp->dir == NULL) {
return T("");
}
return wp->dir;
}
/******************************************************************************/
/*
* Get the flags for this request
*/
int websGetRequestFlags(webs_t wp)
{
a_assert(websValid(wp));
return wp->flags;
}
/******************************************************************************/
/*
* Return the IP address
*/
char_t *websGetRequestIpaddr(webs_t wp)
{
a_assert(websValid(wp));
return wp->ipaddr;
}
/******************************************************************************/
/*
* Set the local path for the request
*/
char_t *websGetRequestLpath(webs_t wp)
{
a_assert(websValid(wp));
#ifdef WEBS_PAGE_ROM
return wp->path;
#else
return wp->lpath;
#endif
}
/******************************************************************************/
/*
* Get the path for this request
*/
char_t *websGetRequestPath(webs_t wp)
{
a_assert(websValid(wp));
if (wp->path == NULL) {
return T("");
}
return wp->path;
}
/******************************************************************************/
/*
* Return the password
*/
char_t *websGetRequestPassword(webs_t wp)
{
a_assert(websValid(wp));
return wp->password;
}
/******************************************************************************/
/*
* Return the request type
*/
char_t *websGetRequestType(webs_t wp)
{
a_assert(websValid(wp));
return wp->type;
}
/******************************************************************************/
/*
* Return the username
*/
char_t *websGetRequestUserName(webs_t wp)
{
a_assert(websValid(wp));
return wp->userName;
}
/******************************************************************************/
/*
* Get the number of bytes written
*/
int websGetRequestWritten(webs_t wp)
{
a_assert(websValid(wp));
return wp->written;
}
/******************************************************************************/
/*
* Set the hostname
*/
void websSetHost(char_t *host)
{
gstrncpy(websHost, host, TSZ(websHost));
}
/******************************************************************************/
/*
* Set the host URL
*/
void websSetHostUrl(char_t *url)
{
a_assert(url && *url);
bfreeSafe(B_L, websHostUrl);
websHostUrl = gstrdup(B_L, url);
}
/******************************************************************************/
/*
* Set the IP address
*/
void websSetIpaddr(char_t *ipaddr)
{
a_assert(ipaddr && *ipaddr);
gstrncpy(websIpaddr, ipaddr, TSZ(websIpaddr));
}
/******************************************************************************/
/*
* Set the number of bytes to write
*/
void websSetRequestBytes(webs_t wp, int bytes)
{
a_assert(websValid(wp));
a_assert(bytes >= 0);
wp->numbytes = bytes;
}
/******************************************************************************/
/*
* Set the flags for this request
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -