📄 hthost.c
字号:
} } return NULL;}/*** Cleanup the host list*/PUBLIC void HTHost_deleteAll (void){ HTList * list; HTHost * host; int i; if (!HostTable) return; for (i=0; i < HOST_HASH_SIZE; i++) { list = HostTable[i]; if (!list) continue; while ((host = (HTHost *) HTList_removeFirstObject(list)) != NULL) free_object(host); HTList_delete(list); } HT_FREE(HostTable); HostTable = NULL;}/*** Get and set the hostname of the remote host*/PUBLIC char * HTHost_name (HTHost * host){ return host ? host->hostname : NULL;}/*** Get and set the type class of the remote host*/PUBLIC char * HTHost_class (HTHost * host){ return host ? host->type : NULL;}PUBLIC void HTHost_setClass (HTHost * host, char * s_class){ if (host && s_class) StrAllocCopy(host->type, s_class);}/*** Get and set the version of the remote host*/PUBLIC int HTHost_version (HTHost *host){ return host ? host->version : 0;}PUBLIC void HTHost_setVersion (HTHost * host, int version){ if (host) host->version = version;}/*** Get and set the passive timeout for persistent entries.*/PUBLIC BOOL HTHost_setPersistTimeout (time_t timeout){ if (timeout > 0) { HTPassiveTimeout = timeout; return YES; } return NO;}PUBLIC time_t HTHost_persistTimeout (void){ return HTPassiveTimeout;}/*** Get and set the active timeout for persistent entries.*/PUBLIC BOOL HTHost_setActiveTimeout (ms_t timeout){ if (timeout > 1000) { HTActiveTimeout = timeout; return YES; } return NO;}PUBLIC ms_t HTHost_activeTimeout (void){ return HTActiveTimeout;}/* Persistent Connection Expiration** --------------------------------** Should normally not be used. If, then use calendar time.*/PUBLIC void HTHost_setPersistExpires (HTHost * host, time_t expires){ if (host) host->expires = expires;}PUBLIC time_t HTHost_persistExpires (HTHost * host){ return host ? host->expires : -1;}PUBLIC void HTHost_setReqsPerConnection (HTHost * host, int reqs){ if (host) host->reqsPerConnection = reqs;}PUBLIC int HTHost_reqsPerConnection (HTHost * host){ return host ? host->reqsPerConnection : -1;}PUBLIC void HTHost_setReqsMade (HTHost * host, int reqs){ if (host) host->reqsMade = reqs;}PUBLIC int HTHost_reqsMade (HTHost * host){ return host ? host->reqsMade : -1;}/*** Public methods for this host*/PUBLIC HTMethod HTHost_publicMethods (HTHost * me){ return me ? me->methods : METHOD_INVALID;}PUBLIC void HTHost_setPublicMethods (HTHost * me, HTMethod methodset){ if (me) me->methods = methodset;}PUBLIC void HTHost_appendPublicMethods (HTHost * me, HTMethod methodset){ if (me) me->methods |= methodset;}/*** Get and set the server name of the remote host*/PUBLIC char * HTHost_server (HTHost * host){ return host ? host->server : NULL;}PUBLIC BOOL HTHost_setServer (HTHost * host, const char * server){ if (host && server) { StrAllocCopy(host->server, server); return YES; } return NO;}/*** Get and set the userAgent name of the remote host*/PUBLIC char * HTHost_userAgent (HTHost * host){ return host ? host->user_agent : NULL;}PUBLIC BOOL HTHost_setUserAgent (HTHost * host, const char * userAgent){ if (host && userAgent) { StrAllocCopy(host->user_agent, userAgent); return YES; } return NO;}/*** Get and set acceptable range units*/PUBLIC char * HTHost_rangeUnits (HTHost * host){ return host ? host->range_units : NULL;}PUBLIC BOOL HTHost_setRangeUnits (HTHost * host, const char * units){ if (host && units) { StrAllocCopy(host->range_units, units); return YES; } return NO;}/*** Checks whether a specific range unit is OK. We always say** YES except if we have a specific statement from the server that** it doesn't understand byte ranges - that is - it has sent "none"** in a "Accept-Range" response header*/PUBLIC BOOL HTHost_isRangeUnitAcceptable (HTHost * host, const char * unit){ if (host && unit) {#if 0 if (host->range_units) { char * start = HTStrCaseStr(host->range_units, "none"); /* ** Check that "none" is infact a token. It could be part of some ** other valid string, so we'd better check for it. */ if (start) { } return NO; }#endif return strcasecomp(unit, "bytes") ? NO : YES; } return NO;}/*** As soon as we know that this host accepts persistent connections,** we associated the channel with the host. ** We don't want more than MaxSockets-2 connections to be persistent in** order to avoid deadlock.*/PUBLIC BOOL HTHost_setPersistent (HTHost * host, BOOL persistent, HTTransportMode mode){ if (!host) return NO; if (!persistent) { /* ** We use the HT_IGNORE status code as we don't want to free ** the stream at this point in time. The situation we want to ** avoid is that we free the channel from within the stream pipe. ** This will lead to an infinite look having the stream freing ** itself. */ host->persistent = NO; return HTHost_clearChannel(host, HT_IGNORE); } /* ** Set the host persistent if not already. Also update the mode to ** the new one - it may have changed */ HTHost_setMode(host, mode); if (!host->persistent) { SOCKET sockfd = HTChannel_socket(host->channel); if (sockfd != INVSOC && HTNet_availablePersistentSockets() > 0) { host->persistent = YES; host->expires = time(NULL) + HTPassiveTimeout; /* Default timeout */ HTChannel_setHost(host->channel, host); HTNet_increasePersistentSocket(); HTTRACE(CORE_TRACE, "Host info... added host %p as persistent\n" _ host); return YES; } else { HTTRACE(CORE_TRACE, "Host info... no room for persistent socket %d\n" _ sockfd); return NO; } } else { HTTRACE(CORE_TRACE, "Host info... %p already persistent\n" _ host); return YES; } return NO;}/*** Check whether we have a persistent channel or not*/PUBLIC BOOL HTHost_isPersistent (HTHost * host){ return host && host->persistent;}/*** Find persistent channel associated with this host.*/PUBLIC HTChannel * HTHost_channel (HTHost * host){ return host ? host->channel : NULL;}/*** Check whether we have got a "close" notification, for example in the** connection header*/PUBLIC BOOL HTHost_setCloseNotification (HTHost * host, BOOL mode){ if (host) { host->close_notification = mode; return YES; } return NO;}PUBLIC BOOL HTHost_closeNotification (HTHost * host){ return host && host->close_notification;}/*** Clear the persistent entry by deleting the channel object. Note that** the channel object is only deleted if it's not used anymore.*/PUBLIC BOOL HTHost_clearChannel (HTHost * host, int status){ if (host && host->channel) { HTChannel_setHost(host->channel, NULL); HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_READ); HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_WRITE); host->registeredFor = 0; /* ** We don't want to recursively delete ourselves so if we are ** called from within the stream pipe then don't delete the channel ** at this point */ HTChannel_delete(host->channel, status); host->expires = 0; host->channel = NULL; host->tcpstate = TCP_BEGIN; host->reqsMade = 0; if (HTHost_isPersistent(host)) { HTNet_decreasePersistentSocket(); host->persistent = NO; } host->close_notification = NO; host->broken_pipe = NO; host->mode = HT_TP_SINGLE; host->recovered = 0; HTTRACE(CORE_TRACE, "Host info... removed host %p as persistent\n" _ host); if (!HTList_isEmpty(host->pending)) { HTTRACE(CORE_TRACE, "Host has %d object(s) pending - attempting launch\n" _ HTList_count(host->pending)); HTHost_launchPending(host); } return YES; } return NO;}PUBLIC BOOL HTHost_doRecover (HTHost * host){ return host ? host->do_recover : NO;}/*** Move all entries in the pipeline and move the rest to the pending** queue. They will get launched at a later point in time.*/PUBLIC BOOL HTHost_recoverPipe (HTHost * host){ if (host) { int piped = HTList_count(host->pipeline); /* ** First check that we haven't already recovered more than we want */ if (host->recovered > MAX_HOST_RECOVER) { HTTRACE(CORE_TRACE, "Host recover %p already %d times - not doing it anymore\n" _ host _ host->recovered); return NO; } /* ** If we decided to recover and actually have something in the pipe ** then go ahead. */ if (piped > 0) { int cnt; host->recovered++; HTTRACE(CORE_TRACE, "Host recover %p recovered %d times. Moving %d Net objects from pipe line to pending queue\n" _ host _ host->recovered _ piped); /* ** Unregister this host for all events */ HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_READ); HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_WRITE); host->registeredFor = 0; /* ** Set new mode to single until we know what is going on */ host->mode = HT_TP_SINGLE; /* ** Move all net objects from the net object to the pending queue. */ if (!host->pending) host->pending = HTList_new(); for (cnt=0; cnt<piped; cnt++) { HTNet * net = HTList_removeLastObject(host->pipeline); HTTRACE(CORE_TRACE, "Host recover Resetting net object %p\n" _ net); net->registeredFor = 0; (*net->event.cbf)(HTChannel_socket(host->channel), net->event.param, HTEvent_RESET); HTList_appendObject(host->pending, net); host->lock = net; } HTChannel_setSemaphore(host->channel, 0); HTHost_clearChannel(host, HT_INTERRUPTED); host->do_recover = NO; } return YES; } return NO;}/*** Terminate a pipeline prematurely, for example because of timeout,** interruption, etc.*/PUBLIC BOOL HTHost_killPipe (HTHost * host){ return killPipeline(host, HTEvent_CLOSE);}/*** Handle the connection mode. The mode may change mode in the ** middle of a connection.*/PUBLIC HTTransportMode HTHost_mode (HTHost * host, BOOL * active){ return host ? host->mode : HT_TP_SINGLE;}/*** If the new mode is lower than the old mode then adjust the pipeline** accordingly. That is, if we are going into single mode then move** all entries in the pipeline and move the rest to the pending** queue. They will get launched at a later point in time.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -