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

📄 nanohttp.c

📁 SIP(Session Initiation Protocol)是由IETF定义
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. *             focuses on size, streamability, reentrancy and portability * * This is clearly not a general purpose HTTP implementation * If you look for one, check: *         http://www.w3.org/Library/ * * See Copyright for the status of this software. * * Daniel.Veillard@w3.org */ /* TODO add compression support, Send the Accept- , and decompress on the        fly with ZLIB if found at compile-time */#include "global.h"#ifdef WIN32#define INCLUDE_WINSOCK#include "win32config.h"#else#include "config.h"#endif#include "xmlversion.h"#ifdef LIBXML_HTTP_ENABLED#include <stdio.h>#include <string.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> #endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <libxml/xmlmemory.h>#include <libxml/nanohttp.h>#ifdef STANDALONE#define DEBUG_HTTP#endif#define XML_NANO_HTTP_MAX_REDIR	10#define XML_NANO_HTTP_CHUNK	4096#define XML_NANO_HTTP_CLOSED	0#define XML_NANO_HTTP_WRITE	1#define XML_NANO_HTTP_READ	2#define XML_NANO_HTTP_NONE	4typedef struct xmlNanoHTTPCtxt {    char *protocol;	/* the protocol name */    char *hostname;	/* the host name */    int port;		/* the port */    char *path;		/* the path within the URL */    int fd;		/* the file descriptor for the socket */    int state;		/* WRITE / READ / CLOSED */    char *out;		/* buffer sent (zero terminated) */    char *outptr;	/* index within the buffer sent */    char *in;		/* the receiving buffer */    char *content;	/* the start of the content */    char *inptr;	/* the next byte to read from network */    char *inrptr;	/* the next byte to give back to the client */    int inlen;		/* len of the input buffer */    int last;		/* return code for last operation */    int returnValue;	/* the protocol return value */    char *contentType;	/* the MIME type for the input */    char *location;	/* the new URL in case of redirect */} xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr;static int initialized = 0;static char *proxy = NULL;	/* the proxy name if any */static int proxyPort;	/* the proxy port if any *//** * xmlNanoHTTPInit: * * Initialize the HTTP protocol layer. * Currently it just checks for proxy informations */voidxmlNanoHTTPInit(void) {    const char *env;    if (initialized)	return;    if (proxy == NULL) {	proxyPort = 80;	env = getenv("no_proxy");	if (env != NULL)	    goto done;	env = getenv("http_proxy");	if (env != NULL) {	    xmlNanoHTTPScanProxy(env);	    goto done;	}	env = getenv("HTTP_PROXY");	if (env != NULL) {	    xmlNanoHTTPScanProxy(env);	    goto done;	}    }done:    initialized = 1;}/** * xmlNanoHTTPClenup: * * Cleanup the HTTP protocol layer. */voidxmlNanoHTTPCleanup(void) {    if (proxy != NULL)	xmlFree(proxy);    initialized = 0;    return;}/** * xmlNanoHTTPScanURL: * @ctxt:  an HTTP context * @URL:  The URL used to initialize the context * * (Re)Initialize an HTTP context by parsing the URL and finding * the protocol host port and path it indicates. */static voidxmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {    const char *cur = URL;    char buf[4096];    int index = 0;    int port = 0;    if (ctxt->protocol != NULL) {         xmlFree(ctxt->protocol);	ctxt->protocol = NULL;    }    if (ctxt->hostname != NULL) {         xmlFree(ctxt->hostname);	ctxt->hostname = NULL;    }    if (ctxt->path != NULL) {         xmlFree(ctxt->path);	ctxt->path = NULL;    }    if (URL == NULL) return;    buf[index] = 0;    while (*cur != 0) {        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {	    buf[index] = 0;	    ctxt->protocol = xmlMemStrdup(buf);	    index = 0;            cur += 3;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0) return;    buf[index] = 0;    while (1) {        if (cur[0] == ':') {	    buf[index] = 0;	    ctxt->hostname = xmlMemStrdup(buf);	    index = 0;	    cur += 1;	    while ((*cur >= '0') && (*cur <= '9')) {	        port *= 10;		port += *cur - '0';		cur++;	    }	    if (port != 0) ctxt->port = port;	    while ((cur[0] != '/') && (*cur != 0)) 	        cur++;	    break;	}        if ((*cur == '/') || (*cur == 0)) {	    buf[index] = 0;	    ctxt->hostname = xmlMemStrdup(buf);	    index = 0;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0)         ctxt->path = xmlMemStrdup("/");    else {        index = 0;        buf[index] = 0;	while (*cur != 0)	    buf[index++] = *cur++;	buf[index] = 0;	ctxt->path = xmlMemStrdup(buf);    }	}/** * xmlNanoHTTPScanProxy: * @URL:  The proxy URL used to initialize the proxy context * * (Re)Initialize the HTTP Proxy context by parsing the URL and finding * the protocol host port it indicates. * Should be like http://myproxy/ or http://myproxy:3128/ * A NULL URL cleans up proxy informations. */voidxmlNanoHTTPScanProxy(const char *URL) {    const char *cur = URL;    char buf[4096];    int index = 0;    int port = 0;    if (proxy != NULL) {         xmlFree(proxy);	proxy = NULL;    }    if (proxyPort != 0) { 	proxyPort = 0;    }#ifdef DEBUG_HTTP    if (URL == NULL)	printf("Removing HTTP proxy info\n");    else	printf("Using HTTP proxy %s\n", URL);#endif    if (URL == NULL) return;    buf[index] = 0;    while (*cur != 0) {        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {	    buf[index] = 0;	    index = 0;            cur += 3;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0) return;    buf[index] = 0;    while (1) {        if (cur[0] == ':') {	    buf[index] = 0;	    proxy = xmlMemStrdup(buf);	    index = 0;	    cur += 1;	    while ((*cur >= '0') && (*cur <= '9')) {	        port *= 10;		port += *cur - '0';		cur++;	    }	    if (port != 0) proxyPort = port;	    while ((cur[0] != '/') && (*cur != 0)) 	        cur++;	    break;	}        if ((*cur == '/') || (*cur == 0)) {	    buf[index] = 0;	    proxy = xmlMemStrdup(buf);	    index = 0;	    break;	}	buf[index++] = *cur++;    }}/** * xmlNanoHTTPNewCtxt: * @URL:  The URL used to initialize the context * * Allocate and initialize a new HTTP context. * * Returns an HTTP context or NULL in case of error. */static xmlNanoHTTPCtxtPtrxmlNanoHTTPNewCtxt(const char *URL) {    xmlNanoHTTPCtxtPtr ret;    ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));    if (ret == NULL) return(NULL);    memset(ret, 0, sizeof(xmlNanoHTTPCtxt));    ret->port = 80;    ret->returnValue = 0;    xmlNanoHTTPScanURL(ret, URL);    return(ret);}/** * xmlNanoHTTPFreeCtxt: * @ctxt:  an HTTP context * * Frees the context after closing the connection. */static voidxmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {    if (ctxt == NULL) return;    if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);    if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);    if (ctxt->path != NULL) xmlFree(ctxt->path);    if (ctxt->out != NULL) xmlFree(ctxt->out);    if (ctxt->in != NULL) xmlFree(ctxt->in);    if (ctxt->contentType != NULL) xmlFree(ctxt->contentType);    if (ctxt->location != NULL) xmlFree(ctxt->location);    ctxt->state = XML_NANO_HTTP_NONE;    if (ctxt->fd >= 0) close(ctxt->fd);    ctxt->fd = -1;    xmlFree(ctxt);}/** * xmlNanoHTTPSend: * @ctxt:  an HTTP context * * Send the input needed to initiate the processing on the server side */static voidxmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt) {    if (ctxt->state & XML_NANO_HTTP_WRITE)	ctxt->last = write(ctxt->fd, ctxt->outptr, strlen(ctxt->outptr));}/** * xmlNanoHTTPRecv: * @ctxt:  an HTTP context * * Read information coming from the HTTP connection. * This is a blocking call (but it blocks in select(), not read()). * * Returns the number of byte read or -1 in case of error. */static intxmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) {    fd_set rfd;    struct timeval tv;    while (ctxt->state & XML_NANO_HTTP_READ) {	if (ctxt->in == NULL) {	    ctxt->in = (char *) xmlMalloc(65000 * sizeof(char));	    if (ctxt->in == NULL) {	        ctxt->last = -1;		return(-1);	    }	    ctxt->inlen = 65000;	    ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;	}	if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {	    int delta = ctxt->inrptr - ctxt->in;	    int len = ctxt->inptr - ctxt->inrptr;	    	    memmove(ctxt->in, ctxt->inrptr, len);	    ctxt->inrptr -= delta;	    ctxt->content -= delta;	    ctxt->inptr -= delta;	}        if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {	    int d_inptr = ctxt->inptr - ctxt->in;	    int d_content = ctxt->content - ctxt->in;	    int d_inrptr = ctxt->inrptr - ctxt->in;	    ctxt->inlen *= 2;            ctxt->in = (char *) xmlRealloc(ctxt->in, ctxt->inlen);	    if (ctxt->in == NULL) {	        ctxt->last = -1;		return(-1);	    }            ctxt->inptr = ctxt->in + d_inptr;            ctxt->content = ctxt->in + d_content;            ctxt->inrptr = ctxt->in + d_inrptr;	}	ctxt->last = read(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK);	if (ctxt->last > 0) {	    ctxt->inptr += ctxt->last;	    return(ctxt->last);	}	if (ctxt->last == 0) {	    return(0);	}#ifdef EWOULDBLOCK	if ((ctxt->last == -1) && (errno != EWOULDBLOCK)) {	    return(0);	}#endif	tv.tv_sec=10;	tv.tv_usec=0;	FD_ZERO(&rfd);	FD_SET(ctxt->fd, &rfd);		if(select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1)		return(0);    }    return(0);}/** * xmlNanoHTTPReadLine: * @ctxt:  an HTTP context * * Read one line in the HTTP server output, usually for extracting * the HTTP protocol informations from the answer header. * * Returns a newly allocated string with a copy of the line, or NULL *         which indicate the end of the input. */static char *xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {    char buf[4096];    char *bp=buf;        while(bp - buf < 4095) {	if(ctxt->inrptr == ctxt->inptr) {	    if (xmlNanoHTTPRecv(ctxt) == 0) {		if (bp == buf)		    return(NULL);		else		    *bp = 0;		return(xmlMemStrdup(buf));	    }	}	*bp = *ctxt->inrptr++;	if(*bp == '\n') {	    *bp = 0;	    return(xmlMemStrdup(buf));	}	if(*bp != '\r')	    bp++;    }    buf[4095] = 0;    return(xmlMemStrdup(buf));}/** * xmlNanoHTTPScanAnswer: * @ctxt:  an HTTP context * @line:  an HTTP header line * * Try to extract useful informations from the server answer. * We currently parse and process: *  - The HTTP revision/ return code *  - The Content-Type *  - The Location for redirrect processing. * * Returns -1 in case of failure, the file descriptor number otherwise */static voidxmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {    const char *cur = line;    if (line == NULL) return;    if (!strncmp(line, "HTTP/", 5)) {        int version = 0;	int ret = 0;	cur += 5;	while ((*cur >= '0') && (*cur <= '9')) {	    version *= 10;	    version += *cur - '0';	    cur++;	}	if (*cur == '.') {	    cur++;	    if ((*cur >= '0') && (*cur <= '9')) {		version *= 10;		version += *cur - '0';		cur++;	    }	    while ((*cur >= '0') && (*cur <= '9'))		cur++;	} else	    version *= 10;	if ((*cur != ' ') && (*cur != '\t')) return;	while ((*cur == ' ') || (*cur == '\t')) cur++;	if ((*cur < '0') || (*cur > '9')) return;	while ((*cur >= '0') && (*cur <= '9')) {	    ret *= 10;	    ret += *cur - '0';	    cur++;	}	if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;	ctxt->returnValue = ret;    } else if (!strncmp(line, "Content-Type:", 13)) {        cur += 13;	while ((*cur == ' ') || (*cur == '\t')) cur++;	if (ctxt->contentType != NULL)	    xmlFree(ctxt->contentType);	ctxt->contentType = xmlMemStrdup(cur);    } else if (!strncmp(line, "ContentType:", 12)) {        cur += 12;	if (ctxt->contentType != NULL) return;	while ((*cur == ' ') || (*cur == '\t')) cur++;	ctxt->contentType = xmlMemStrdup(cur);    } else if (!strncmp(line, "content-type:", 13)) {        cur += 13;	if (ctxt->contentType != NULL) return;	while ((*cur == ' ') || (*cur == '\t')) cur++;	ctxt->contentType = xmlMemStrdup(cur);    } else if (!strncmp(line, "contenttype:", 12)) {        cur += 12;	if (ctxt->contentType != NULL) return;	while ((*cur == ' ') || (*cur == '\t')) cur++;	ctxt->contentType = xmlMemStrdup(cur);    } else if (!strncmp(line, "Location:", 9)) {        cur += 9;	while ((*cur == ' ') || (*cur == '\t')) cur++;	if (ctxt->location != NULL)	    xmlFree(ctxt->location);	ctxt->location = xmlMemStrdup(cur);    } else if (!strncmp(line, "location:", 9)) {        cur += 9;	if (ctxt->location != NULL) return;	while ((*cur == ' ') || (*cur == '\t')) cur++;	ctxt->location = xmlMemStrdup(cur);    }}/** * xmlNanoHTTPConnectAttempt: * @ia:  an internet adress structure * @port:  the port number * * Attempt a connection to the given IP:port endpoint. It forces * non-blocking semantic on the socket, and allow 60 seconds for * the host to answer. * * Returns -1 in case of failure, the file descriptor number otherwise */static intxmlNanoHTTPConnectAttempt(struct in_addr ia, int port){    int s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    struct sockaddr_in sin;    fd_set wfd;    struct timeval tv;    int status;        if(s==-1) {#ifdef DEBUG_HTTP	perror("socket");#endif	return(-1);    }    #ifdef _WINSOCKAPI_    {	long levents = FD_READ | FD_WRITE | FD_ACCEPT |		       FD_CONNECT | FD_CLOSE ;	int rv = 0 ;	u_long one = 1;	status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;    }#else /* _WINSOCKAPI_ */#if defined(VMS)    {	int enable = 1;	status = IOCTL(s, FIONBIO, &enable);    }#else /* VMS */    if((status = fcntl(s, F_GETFL, 0)) != -1) {#ifdef O_NONBLOCK	status |= O_NONBLOCK;#else /* O_NONBLOCK */#ifdef F_NDELAY	status |= F_NDELAY;#endif /* F_NDELAY */#endif /* !O_NONBLOCK */	status = fcntl(s, F_SETFL, status);    }    if(status < 0) {#ifdef DEBUG_HTTP	perror("nonblocking");#endif	close(s);	return(-1);    }#endif /* !VMS */

⌨️ 快捷键说明

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