Annotation of libwww/Library/src/HTHost.c, revision 2.1

2.1     ! frystyk     1: /*                                                                    HTHost.c
        !             2: **     REMOTE HOST INFORMATION
        !             3: **
        !             4: **     (c) COPYRIGHT MIT 1995.
        !             5: **     Please first read the full copyright statement in the file COPYRIGH.
        !             6: **     @(#) $Id: Date Author State $
        !             7: **
        !             8: **     This object manages the information that we know about a remote host.
        !             9: **     This can for example be what type of host it is, and what version
        !            10: **     it is using. We also keep track of persistent connections
        !            11: **
        !            12: **     April 96  HFN   Written
        !            13: */
        !            14: 
        !            15: /* Library include files */
        !            16: #include "sysdep.h"
        !            17: #include "WWWUtil.h"
        !            18: #include "HTParse.h"
        !            19: #include "HTAlert.h"
        !            20: #include "HTError.h"
        !            21: #include "HTNetMan.h"
        !            22: #include "HTTrans.h"
        !            23: #include "HTHost.h"                                     /* Implemented here */
        !            24: 
        !            25: #define HOST_TIMEOUT           43200L       /* Default host timeout is 12 h */
        !            26: #define TCP_TIMEOUT            3600L           /* Default TCP timeout i 1 h */
        !            27: #define HASH_SIZE              67
        !            28: 
        !            29: /* Type definitions and global variables etc. local to this module */
        !            30: struct _HTHost {
        !            31:     char *             hostname;            /* name of host + optional port */
        !            32:     time_t             ntime;                              /* Creation time */
        !            33:     char *             type;                                   /* Peer type */
        !            34:     int                version;                             /* Peer version */
        !            35:     HTChannelMode      mode;                              /* Supported mode */
        !            36:     HTChannel *                channel;                       /* Persistent channel */
        !            37:     time_t             expires;          /* Persistent channel expires time */
        !            38: };
        !            39: 
        !            40: PRIVATE HTList ** HostTable = NULL;
        !            41: PRIVATE time_t HostTimeout = HOST_TIMEOUT;       /* Timeout on host entries */
        !            42: PRIVATE time_t TCPTimeout = TCP_TIMEOUT;  /* Timeout on persistent channels */
        !            43: 
        !            44: PRIVATE HTList * Persistent = NULL;           /* List of persistent sockets */
        !            45: 
        !            46: /* ------------------------------------------------------------------------- */
        !            47: 
        !            48: PRIVATE void free_object (HTHost * me)
        !            49: {
        !            50:     if (me) {
        !            51:        HT_FREE(me->hostname);
        !            52:        HT_FREE(me->type);
        !            53:        if (me->channel) HTChannel_delete(me->channel);
        !            54:        HT_FREE(me);
        !            55:     }
        !            56: }
        !            57: 
        !            58: PRIVATE BOOL delete_object (HTList * list, HTHost * me)
        !            59: {
        !            60:     if (PROT_TRACE) HTTrace("Host info... object %p from list %p\n", me, list);
        !            61:     HTList_removeObject(list, (void *) me);
        !            62:     free_object(me);
        !            63:     return YES;
        !            64: }
        !            65: 
        !            66: /*
        !            67: **     Search the host info cache for a host object or create a new one
        !            68: **     and add it. Examples of host names are
        !            69: **
        !            70: **             www.w3.org
        !            71: **             www.foo.com:8000
        !            72: **             18.52.0.18
        !            73: **
        !            74: **     Returns Host object or NULL if error. You may get back an already
        !            75: **     existing host object - you're not guaranteed a new one each time.
        !            76: */
        !            77: PUBLIC HTHost * HTHost_new (char * host)
        !            78: {
        !            79:     HTList * list = NULL;                          /* Current list in cache */
        !            80:     HTHost * pres = NULL;
        !            81:     if (!host) {
        !            82:        if (PROT_TRACE) HTTrace("Host info... Bad argument\n");
        !            83:        return NULL;
        !            84:     }
        !            85:     
        !            86:     /* Find a hash for this host */
        !            87:     {
        !            88:        int hash = 0;
        !            89:        char *ptr;
        !            90:        for (ptr=host; *ptr; ptr++)
        !            91:            hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HASH_SIZE);
        !            92:        if (!HostTable) {
        !            93:            if ((HostTable = (HTList **) HT_CALLOC(HASH_SIZE,
        !            94:                                                   sizeof(HTList *))) == NULL)
        !            95:                HT_OUTOFMEM("HTHost_find");
        !            96:        }
        !            97:        if (!HostTable[hash]) HostTable[hash] = HTList_new();
        !            98:        list = HostTable[hash];
        !            99:     }
        !           100: 
        !           101:     /* Search the cache */
        !           102:     {
        !           103:        HTList * cur = list;
        !           104:        while ((pres = (HTHost *) HTList_nextObject(cur))) {
        !           105:            if (!strcmp(pres->hostname, host)) {
        !           106:                if (time(NULL) > pres->ntime + HostTimeout) {
        !           107:                    if (PROT_TRACE)
        !           108:                        HTTrace("Host info... Collecting host info %p\n",pres);
        !           109:                    delete_object(list, pres);
        !           110:                    pres = NULL;
        !           111:                }
        !           112:                break;
        !           113:            }
        !           114:        }
        !           115:     }
        !           116: 
        !           117:     /* If not found then create new Host object */
        !           118:     if (pres) {
        !           119:        if (pres->channel) {
        !           120:            if (pres->expires < time(NULL)) {      /* Cached channel is cold */
        !           121:                if (PROT_TRACE)
        !           122:                    HTTrace("Host info... Persistent channel %p gotten cold\n",
        !           123:                            pres->channel);
        !           124:                HTChannel_delete(pres->channel);
        !           125:                pres->channel = NULL;
        !           126:            } else {
        !           127:                if (PROT_TRACE)
        !           128:                    HTTrace("Host info... REUSING CHANNEL %p\n",pres->channel);
        !           129:            }
        !           130:        }
        !           131:     } else {
        !           132:        if ((pres = (HTHost *) HT_CALLOC(1, sizeof(HTHost))) == NULL)
        !           133:            HT_OUTOFMEM("HTHost_add");
        !           134:        StrAllocCopy(pres->hostname, host);
        !           135:        pres->ntime = time(NULL);
        !           136:        if (PROT_TRACE) 
        !           137:            HTTrace("Host info... added `%s\' to list %p\n", host, list);
        !           138:        HTList_addObject(list, (void *) pres);
        !           139:     }
        !           140:     return pres;
        !           141: }
        !           142: 
        !           143: /*
        !           144: **     Get and set the type class of the remote host
        !           145: */
        !           146: PUBLIC char * HTHost_class (HTHost * host)
        !           147: {
        !           148:      return host ? host->type : NULL;
        !           149: }
        !           150: 
        !           151: PUBLIC void HTHost_setClass (HTHost * host, char * s_class)
        !           152: {
        !           153:     if (host && s_class) StrAllocCopy(host->type, s_class);
        !           154: }
        !           155: 
        !           156: /*
        !           157: **     Get and set the version of the remote host
        !           158: */
        !           159: PUBLIC int HTHost_version (HTHost *host)
        !           160: {
        !           161:      return host ? host->version : 0;
        !           162: }
        !           163: 
        !           164: PUBLIC void HTHost_setVersion (HTHost * host, int version)
        !           165: {
        !           166:     if (host) host->version = version;
        !           167: }
        !           168: 
        !           169: /*
        !           170: **     Get and set the cache timeout for persistent entries.
        !           171: **     The default value is TCP_TIMEOUT
        !           172: */
        !           173: PUBLIC void HTHost_setPersistTimeout (time_t timeout)
        !           174: {
        !           175:     TCPTimeout = timeout;
        !           176: }
        !           177: 
        !           178: PUBLIC time_t HTHost_persistTimeout (time_t timeout)
        !           179: {
        !           180:     return TCPTimeout;
        !           181: }
        !           182: 
        !           183: /*     Persistent Connection Expiration
        !           184: **     --------------------------------
        !           185: **     Should normally not be used. If, then use calendar time.
        !           186: */
        !           187: PUBLIC void HTHost_setPersistExpires (HTHost * host, time_t expires)
        !           188: {
        !           189:     if (host) host->expires = expires;
        !           190: }
        !           191: 
        !           192: PUBLIC time_t HTHost_persistExpires (HTHost * host)
        !           193: {
        !           194:     return host ? host->expires : -1;
        !           195: }
        !           196: 
        !           197: /*
        !           198: **     Searches the list of persistent connections for a host object
        !           199: **     associated with this channel
        !           200: */
        !           201: PRIVATE HTHost * HTHost_findPersistent (HTChannel * ch)
        !           202: {
        !           203:     if (Persistent && ch) {
        !           204:        HTList * cur = Persistent;
        !           205:        HTHost * pres;
        !           206:        while ((pres = (HTHost *) HTList_nextObject(cur)))
        !           207:            if (pres->channel == ch) return pres;
        !           208:     }
        !           209:     return NULL;
        !           210: }
        !           211: 
        !           212: /*     HTHost_catchClose
        !           213: **     -----------------
        !           214: **     This function is registered when the socket is idle so that we get
        !           215: **     a notification if the socket closes at the other end. At this point
        !           216: **     we can't use the request object as it might have been freed a long
        !           217: **     time ago.
        !           218: */
        !           219: PUBLIC int HTHost_catchClose (SOCKET soc, HTRequest * request, SockOps ops)
        !           220: {
        !           221:     if (PROT_TRACE)
        !           222:        HTTrace("Catch Close. called with socket %d with ops %x\n",
        !           223:                soc, (unsigned) ops);
        !           224:     if (ops == FD_READ) {
        !           225:        HTChannel * ch = HTChannel_find(soc);     /* Find associated channel */
        !           226:        HTHost * host = HTHost_findPersistent(ch);
        !           227:        if (ch && host) {           
        !           228:            if (PROT_TRACE) HTTrace("Catch Close. CLOSING socket %d\n", soc);
        !           229:            HTHost_clearChannel(host);
        !           230:        } else {
        !           231:            if (PROT_TRACE) HTTrace("Catch Close. socket %d NOT FOUND!\n",soc);
        !           232:        }
        !           233:     }
        !           234:     HTEvent_UnRegister(soc, (SockOps) FD_ALL);
        !           235:     return HT_OK;
        !           236: }
        !           237: 
        !           238: /*
        !           239: **     As soon as we know that this host accepts persistent connections,
        !           240: **     we associated the channel with the host. 
        !           241: **     We don't want more than MaxSockets-2 connections to be persistent in
        !           242: **     order to avoid deadlock.
        !           243: */
        !           244: PUBLIC BOOL HTHost_setChannel (HTHost * host, HTChannel * channel)
        !           245: {
        !           246:     if (host && channel) {
        !           247:        SOCKET sockfd = HTChannel_socket(channel);
        !           248:        if (!Persistent) Persistent = HTList_new();
        !           249:        if (sockfd != INVSOC && HTList_count(Persistent)<HTNet_maxSocket()-2) {
        !           250:            host->channel = channel;
        !           251:            host->expires = time(NULL) + TCPTimeout;      /* Default timeout */
        !           252:            HTList_addObject(Persistent, host);
        !           253:            if (PROT_TRACE)
        !           254:                HTTrace("Host info... added host %p as persistent\n", host);
        !           255:            return YES;
        !           256:        } else {
        !           257:            if (PROT_TRACE)
        !           258:                HTTrace("Host info... no room for persistent cocket %d\n",
        !           259:                        socket);
        !           260:        }
        !           261:     }
        !           262:     return NO;
        !           263: }
        !           264: 
        !           265: /*
        !           266: **     Find persistent channel associated with this host.
        !           267: */
        !           268: PUBLIC HTChannel * HTHost_channel (HTHost * host)
        !           269: {
        !           270:     return host ? host->channel : NULL;
        !           271: }
        !           272: 
        !           273: /*
        !           274: **     Clear the persistent entry by deleting the channel object. Note that
        !           275: **     the channel object is only deleted if it's not used anymore.
        !           276: */
        !           277: PUBLIC BOOL HTHost_clearChannel (HTHost * host)
        !           278: {
        !           279:     if (host && host->channel) {
        !           280:        HTChannel_delete(host->channel);
        !           281:        host->expires = 0;
        !           282:        host->channel = NULL;
        !           283:        HTList_removeObject(Persistent, host);
        !           284:        return YES;
        !           285:     }
        !           286:     return NO;
        !           287: }
        !           288: 
        !           289: /*
        !           290: **     Check whether we have a persistent channel or not
        !           291: */
        !           292: PUBLIC BOOL HTHost_isPersistent (HTHost * host)
        !           293: {
        !           294:     return host && host->channel;
        !           295: }
        !           296: 

Webmaster