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

📄 webs.c

📁 嵌入式Linux系统用的web server,开源代码,非常好用
💻 C
📖 第 1 页 / 共 5 页
字号:

	va_start(vargs, fmt);

	buf = NULL;
	rc = 0;

	if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {
		trace(0, T("webs: websWrite lost data, buffer overflow\n"));
	}
   
	va_end(vargs);
	a_assert(buf);
	if (buf) {
		rc = websWriteBlock(wp, buf, gstrlen(buf));
		bfree(B_L, buf);
	}
	return rc;
}

/******************************************************************************/
/*
 *	Write a block of data of length "nChars" to the user's browser. Public
 *	write block procedure.  If unicode is turned on this function expects 
 *	buf to be a unicode string and it converts it to ASCII before writing.
 *	See websWriteDataNonBlock to always write binary or ASCII data with no 
 *	unicode conversion.  This returns the number of char_t's processed.
 *	It spins until nChars are flushed to the socket.  For non-blocking
 *	behavior, use websWriteDataNonBlock.
 */

int websWriteBlock(webs_t wp, char_t *buf, int nChars)
{
	int		len, done;
	char	*asciiBuf, *pBuf;

	a_assert(wp);
	a_assert(websValid(wp));
	a_assert(buf);
	a_assert(nChars >= 0);

	done = len = 0;

/*
 *	ballocUniToAsc will convert Unicode to strings to Ascii.  If Unicode is
 *	not turned on then ballocUniToAsc will not do the conversion.
 */
	pBuf = asciiBuf = ballocUniToAsc(buf, nChars);

	while (nChars > 0) {  
#ifdef WEBS_SSL_SUPPORT
		if (wp->flags & WEBS_SECURE) {
			if ((len = websSSLWrite(wp->wsp, pBuf, nChars)) < 0) {
				bfree(B_L, asciiBuf);
				return -1;
			}
			websSSLFlush(wp->wsp);
		} else {
			if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
				bfree(B_L, asciiBuf);
				return -1;
			}
			socketFlush(wp->sid);
		}
#else /* ! WEBS_SSL_SUPPORT */
		if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
			bfree(B_L, asciiBuf);
			return -1;
		}
		socketFlush(wp->sid);
#endif /* WEBS_SSL_SUPPORT */
		nChars -= len;
		pBuf += len;
		done += len;
	}

	bfree(B_L, asciiBuf);
	return done;
}

/******************************************************************************/
/*
 *	Write a block of data of length "nChars" to the user's browser. Same as
 *	websWriteBlock except that it expects straight ASCII or binary and does no
 *	unicode conversion before writing the data.  If the socket cannot hold all
 *	the data, it will return the number of bytes flushed to the socket before
 *	it would have blocked.  This returns the number of chars processed or -1
 *	if socketWrite fails.
 */

int websWriteDataNonBlock(webs_t wp, char *buf, int nChars)
{
	int r;

	a_assert(wp);
	a_assert(websValid(wp));
	a_assert(buf);
	a_assert(nChars >= 0);

#ifdef WEBS_SSL_SUPPORT
	if (wp->flags & WEBS_SECURE) {
		r = websSSLWrite(wp->wsp, buf, nChars);
		websSSLFlush(wp->wsp);
	} else {
		r = socketWrite(wp->sid, buf, nChars);
		socketFlush(wp->sid);
	}
#else
	r = socketWrite(wp->sid, buf, nChars);
	socketFlush(wp->sid);
#endif

	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
#if (defined(qAnlLog) && !defined(CE))
   time_t timer;
   char_t* newLine = NULL;
   char_t* timeStr = NULL;
#endif
	a_assert(websValid(wp));

	buf = NULL;

#if (defined(qAnlLog) && !defined(CE))
   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));

⌨️ 快捷键说明

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