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

📄 hthost.c

📁 www工具包. 这是W3C官方支持的www支撑库. 其中提供通用目的的客户端的WebAPI: complete HTTP/1.1 (with caching, pipelining, PUT, POS
💻 C
📖 第 1 页 / 共 4 页
字号:
/*								       HTHost.c**	REMOTE HOST INFORMATION****	(c) COPYRIGHT MIT 1995.**	Please first read the full copyright statement in the file COPYRIGH.**	@(#) $Id: HTHost.c,v 2.72 2000/07/28 13:56:08 kahan Exp $****	This object manages the information that we know about a remote host.**	This can for example be what type of host it is, and what version**	it is using. We also keep track of persistent connections****	April 96  HFN	Written*//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "HTParse.h"#include "HTAlert.h"#include "HTError.h"#include "HTNetMan.h"#include "HTTrans.h"#include "HTTPUtil.h"#include "HTTCP.h"#include "HTHost.h"					 /* Implemented here */#include "HTHstMan.h"#define HOST_OBJECT_TTL	    43200L	     /* Default host timeout is 12 h */#define TCP_IDLE_PASSIVE      120L /* Passive TTL in s on an idle connection */#define TCP_IDLE_ACTIVE     60000L /* Active TTL in ms on an idle connection */#define MAX_PIPES		50   /* maximum number of pipelined requests */#define MAX_HOST_RECOVER	1	      /* Max number of auto recovery */#define DEFAULT_DELAY		30	  /* Default write flush delay in ms */struct _HTInputStream {    const HTInputStreamClass *	isa;};PRIVATE int HostEvent(SOCKET soc, void * pVoid, HTEventType type);/* Type definitions and global variables etc. local to this module */PRIVATE time_t	HostTimeout = HOST_OBJECT_TTL;	 /* Timeout for host objects */PRIVATE time_t	HTPassiveTimeout = TCP_IDLE_PASSIVE; /* Passive timeout in s */PRIVATE ms_t	HTActiveTimeout = TCP_IDLE_ACTIVE;   /* Active timeout in ms */PRIVATE HTList	** HostTable = NULL;PRIVATE HTList * PendHost = NULL;	    /* List of pending host elements *//* JK: New functions for interruption the automatic pending request    activation */PRIVATE HTHost_ActivateRequestCallback * ActivateReqCBF = NULL;PRIVATE int HTHost_ActivateRequest (HTNet *net);PRIVATE BOOL DoPendingReqLaunch = YES; /* controls automatic activation                                              of pending requests */PRIVATE int EventTimeout = -1;		        /* Global Host event timeout */PRIVATE ms_t WriteDelay = DEFAULT_DELAY;		      /* Delay in ms */PRIVATE int MaxPipelinedRequests = MAX_PIPES;/* ------------------------------------------------------------------------- */PRIVATE void free_object (HTHost * me){    if (me) {	int i;	HT_FREE(me->hostname);	HT_FREE(me->type);	HT_FREE(me->server);	HT_FREE(me->user_agent);	HT_FREE(me->range_units);	/* Delete the channel (if any) */	if (me->channel) {	    HTChannel_delete(me->channel, HT_OK);	    me->channel = NULL;	}	/* Unregister the events */	for (i = 0; i < HTEvent_TYPES; i++)	    HTEvent_delete(me->events[i]);	/* Delete the timer (if any) */	if (me->timer) HTTimer_delete(me->timer);	/* Delete the queues */	HTList_delete(me->pipeline);	HTList_delete(me->pending);	HT_FREE(me);    }}PRIVATE BOOL delete_object (HTList * list, HTHost * me){    HTTRACE(CORE_TRACE, "Host info... object %p from list %p\n" _ me _ list);    HTList_removeObject(list, (void *) me);    free_object(me);    return YES;}PRIVATE BOOL isLastInPipe (HTHost * host, HTNet * net){    return HTList_lastObject(host->pipeline) == net;}PRIVATE BOOL killPipeline (HTHost * host, HTEventType type){    if (host) {	int piped = HTList_count(host->pipeline);	int pending = HTList_count(host->pending);	int cnt;	HTTRACE(CORE_TRACE, "Host kill... Pipeline due to %s event\n" _ HTEvent_type2str(type));	/* Terminate all net objects in pending queue */	for (cnt=0; cnt<pending; cnt++) {	    HTNet * net = HTList_removeLastObject(host->pending);	    if (net) {		HTTRACE(CORE_TRACE, "Host kill... Terminating net object %p from pending queue\n" _ net);		net->registeredFor = 0;		(*net->event.cbf)(HTChannel_socket(host->channel), net->event.param, type);		if (host->lock == net) host->lock = NULL;	    }	}	/* Terminate all net objects in pipeline */	if (piped >= 1) {	    	    /*	    **  Terminte all net objects in the pipeline	    */	    for (cnt=0; cnt<piped; cnt++) {		HTNet * net = HTList_firstObject(host->pipeline);		if (net) {		    HTTRACE(CORE_TRACE, "Host kill... Terminating net object %p from pipe line\n" _ net);		    net->registeredFor = 0;		    (*net->event.cbf)(HTChannel_socket(host->channel), net->event.param, type);		}	    }	}	return YES;    }    return NO;}/***  Silently close an idle persistent connection after **  HTActiveTimeout secs*/PRIVATE int IdleTimeoutEvent (HTTimer * timer, void * param, HTEventType type){    HTHost * host = (HTHost *) param;    SOCKET sockfd = HTChannel_socket(host->channel);    HTTimer_delete(timer);    host->timer = NULL;    return HostEvent (sockfd, host, HTEvent_CLOSE);}/***	HostEvent - host event manager - recieves events from the event **	manager and dispatches them to the client net objects by calling the **	net object's cbf.***/PRIVATE int HostEvent (SOCKET soc, void * pVoid, HTEventType type){    HTHost * host = (HTHost *)pVoid;    if (type == HTEvent_READ || type == HTEvent_CLOSE || type == HTEvent_ACCEPT) {	HTNet * targetNet;	/* call the first net object */	do {	    int ret;            /* netscape and apache servers can do a lazy close well after usage             * of previous socket has been dispensed by the library,             * the section below makes sure the event does not get miss attributed             */	    if (HTChannel_socket(host->channel) != soc && type != HTEvent_ACCEPT && !host->listening) {		HTTRACE(CORE_TRACE, "Host Event.. wild socket %d type = %s real socket is %d\n" _ soc _ 			type == HTEvent_CLOSE ? "Event_Close" : "Event_Read" _ 			HTChannel_socket(host->channel));		return HT_OK;	    }	    targetNet = (HTNet *)HTList_firstObject(host->pipeline);	    if (targetNet) {		HTTRACE(CORE_TRACE, "Host Event.. READ passed to `%s\'\n" _ 			    HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet))));		if ((ret = (*targetNet->event.cbf)(HTChannel_socket(host->channel), 						  targetNet->event.param, type)) != HT_OK)		    return ret;	    }	    if (targetNet == NULL && host->remainingRead > 0) {		HTTRACE(CORE_TRACE, "HostEvent... Error: %d bytes left to read and nowhere to put them\n" _ 			    host->remainingRead);		host->remainingRead = 0;		/*		**	Fall through to close the channel		*/	    }	/* call pipelined net object to eat all the data in the channel */	} while (host->remainingRead > 0);	/* last target net should have set remainingRead to 0 */	if (targetNet)	    return HT_OK;	/* If there was notargetNet, it should be a close */	HTTRACE(CORE_TRACE, "Host Event.. host %p `%s\' closed connection.\n" _ 		    host _ host->hostname);	/* Is there garbage in the channel? Let's check: */	{	    char buf[256];	    int ret;	    memset(buf, '\0', sizeof(buf));	    if (HTChannel_socket(host->channel) != INVSOC) {	      while ((ret = NETREAD(HTChannel_socket(host->channel), buf, sizeof(buf)-1)) > 0) {		HTTRACE(CORE_TRACE, "Host Event.. Host %p `%s\' had %d extraneous bytes: `%s\'\n" _ 			host _ host->hostname _ ret _ buf);		memset(buf, '\0', sizeof(buf));			      }	    	    }	}	HTHost_clearChannel(host, HT_OK);	return HT_OK; 	     /* extra garbage does not constitute an application error */	    } else if (type == HTEvent_WRITE || type == HTEvent_CONNECT) {	HTNet * targetNet = (HTNet *)HTList_lastObject(host->pipeline);	if (targetNet) {	    HTTRACE(CORE_TRACE, "Host Event.. WRITE passed to `%s\'\n" _ 			HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet))));	    return (*targetNet->event.cbf)(HTChannel_socket(host->channel), targetNet->event.param, type);	}	HTTRACE(CORE_TRACE, "Host Event Host %p (`%s\') dispatched with event %s but doesn't have a target - %d requests made, %d requests in pipe, %d pending\n" _ 		    host _ 		    host ? host->hostname : "<null>" _ 		    HTEvent_type2str(type) _ 		    host ? host->reqsMade : -1 _ 		    HTList_count(host->pipeline) _ 		    HTList_count(host->pending));#if 0	HTDEBUGBREAK("Host Event.. Host %p (`%s\') dispatched with event %d\n" _ 		     host _ host ? host->hostname : "<null>" _ type);	return HT_ERROR;#else	return HT_OK;#endif    } else if (type == HTEvent_TIMEOUT) {	killPipeline(host, HTEvent_TIMEOUT);    } else {	HTTRACE(CORE_TRACE, "Don't know how to handle OOB data from `%s\'?\n" _		host->hostname);    }    return HT_OK;}/***	Search the host info cache for a host object or create a new one**	and add it. Examples of host names are****		www.w3.org**		www.foo.com:8000**		18.52.0.18****	Returns Host object or NULL if error. You may get back an already**	existing host object - you're not guaranteed a new one each time.*/PUBLIC HTHost * HTHost_new (char * host, u_short u_port){    HTList * list = NULL;			    /* Current list in cache */    HTHost * pres = NULL;    int hash = 0;    if (!host) {	HTTRACE(CORE_TRACE, "Host info... Bad argument\n");	return NULL;    }        /* Find a hash for this host */    {	char *ptr;	for (ptr=host; *ptr; ptr++)	    hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HOST_HASH_SIZE);	if (!HostTable) {	    if ((HostTable = (HTList **) HT_CALLOC(HOST_HASH_SIZE,						   sizeof(HTList *))) == NULL)	        HT_OUTOFMEM("HTHost_find");	}	if (!HostTable[hash]) HostTable[hash] = HTList_new();	list = HostTable[hash];    }    /* Search the cache */    {	HTList * cur = list;	while ((pres = (HTHost *) HTList_nextObject(cur))) {	    if (!strcmp(pres->hostname, host) && u_port == pres->u_port) {		if (HTHost_isIdle(pres) && time(NULL)>pres->ntime+HostTimeout){		    HTTRACE(CORE_TRACE, "Host info... Collecting host info %p\n" _ pres);		    delete_object(list, pres);		    pres = NULL;		}		break;	    }	}    }    /* If not found then create new Host object, else use existing one */    if (pres) {	if (pres->channel) {            /*            **  If we have a TTL for this TCP connection then            **  check that we haven't passed it.            */            if (pres->expires > 0) {                time_t t = time(NULL);                if (HTHost_isIdle(pres) && pres->expires < t) {                    HTTRACE(CORE_TRACE, "Host info... Persistent channel %p gotten cold\n" _                         pres->channel);		    HTHost_clearChannel(pres, HT_OK);                } else {                    pres->expires = t + HTPassiveTimeout;                    HTTRACE(CORE_TRACE, "Host info... REUSING CHANNEL %p\n" _ pres->channel);                }            }	} else {	    HTTRACE(CORE_TRACE, "Host info... Found Host %p with no active channel\n" _ pres);	}    } else {	if ((pres = (HTHost *) HT_CALLOC(1, sizeof(HTHost))) == NULL)	    HT_OUTOFMEM("HTHost_add");	pres->hash = hash;	StrAllocCopy(pres->hostname, host);	pres->u_port = u_port;	pres->ntime = time(NULL);	pres->mode = HT_TP_SINGLE;	pres->delay = WriteDelay;	pres->inFlush = NO;	{	    int i;	    for (i = 0; i < HTEvent_TYPES; i++)		pres->events[i]= HTEvent_new(HostEvent, pres, HT_PRIORITY_MAX, EventTimeout);	}	HTTRACE(CORE_TRACE, "Host info... added `%s\' with host %p to list %p\n" _ 		    host _ pres _ list);	HTList_addObject(list, (void *) pres);    }    return pres;}PUBLIC HTHost * HTHost_newWParse (HTRequest * request, char * url, u_short u_port){    char * port;    char * fullhost = NULL;    char * parsedHost = NULL;    SockA * sin;    HTHost * me;    char * proxy = HTRequest_proxy(request);    fullhost = HTParse(proxy ? proxy : url, "", PARSE_HOST);    /* If there's an @ then use the stuff after it as a hostname */    if (fullhost) {	char * at_sign;	if ((at_sign = strchr(fullhost, '@')) != NULL)	    parsedHost = at_sign+1;	else	    parsedHost = fullhost;    }    if (!parsedHost || !*parsedHost) {	HTRequest_addError(request, ERR_FATAL, NO, HTERR_NO_HOST,			   NULL, 0, "HTHost_newWParse");	HT_FREE(fullhost);	return NULL;    }    /* See if the default port should be overridden */    if ((port = strchr(parsedHost, ':')) != NULL) {	*port++ = '\0';	if (*port && isdigit((int) *port)) u_port = (u_short) atol(port);    }    HTTRACE(PROT_TRACE, "HTHost parse Looking up `%s\' on port %u\n" _ parsedHost _ u_port);    /* Find information about this host */    if ((me = HTHost_new(parsedHost, u_port)) == NULL) {	HTTRACE(PROT_TRACE, "HTHost parse Can't get host info\n");	me->tcpstate = TCP_ERROR;	return NULL;    }    sin = &me->sock_addr;    memset((void *) sin, '\0', sizeof(SockA));#ifdef DECNET    sin->sdn_family = AF_DECnet;    net->sock_addr.sdn_objnum = port ? (unsigned char)(strtol(port, (char **) 0, 10)) : DNP_OBJ;#else  /* Internet */    sin->sin_family = AF_INET;    sin->sin_port = htons(u_port);#endif    HT_FREE(fullhost);	/* parsedHost points into fullhost */    return me;}/***	Search the host info cache for a host object. Examples of host names:****		www.w3.org**		www.foo.com:8000**		18.52.0.18****	Returns Host object or NULL if not found.*/PUBLIC HTHost * HTHost_find (char * host){    HTList * list = NULL;			    /* Current list in cache */    HTHost * pres = NULL;    HTTRACE(CORE_TRACE, "Host info... Looking for `%s\'\n" _ host ? host : "<null>");    /* Find a hash for this host */    if (host && HostTable) {	int hash = 0;	char *ptr;	for (ptr=host; *ptr; ptr++)	    hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HOST_HASH_SIZE);	if (!HostTable[hash]) return NULL;	list = HostTable[hash];	/* Search the cache */	{	    HTList * cur = list;	    while ((pres = (HTHost *) HTList_nextObject(cur))) {		if (!strcmp(pres->hostname, host)) {		    if (time(NULL) > pres->ntime + HostTimeout) {			HTTRACE(CORE_TRACE, "Host info... Collecting host %p\n" _ pres);			delete_object(list, pres);			pres = NULL;  		    } else {			HTTRACE(CORE_TRACE, "Host info... Found `%s\'\n" _ host);		    }		    return pres;		}	    }

⌨️ 快捷键说明

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