Annotation of libwww/Library/src/HTChannl.c, revision 2.12.2.3

2.1       frystyk     1: /*                                                                  HTChannl.c
                      2: **     CONTAINS STREAMS FOR READING AND WRITING TO AND FROM A TRANSPORT
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.12.2.3! eric        6: **     @(#) $Id: HTChannl.c,v 2.12.2.2 1996/11/02 19:26:20 eric Exp $
2.1       frystyk     7: **
                      8: **
                      9: ** HISTORY:
                     10: **     April 96  HFN   Written
                     11: */
                     12: 
                     13: /* Library Include files */
                     14: #include "sysdep.h"
                     15: #include "WWWUtil.h"
                     16: #include "HTAlert.h"
2.10      frystyk    17: #include "HTHost.h"
2.1       frystyk    18: #include "HTError.h"
                     19: #include "HTChannl.h"                                   /* Implemented here */
                     20: 
                     21: #define HASH_SIZE      67
                     22: #define HASH(s)                ((s) % HASH_SIZE)
                     23: 
                     24: struct _HTChannel {
                     25:     SOCKET             sockfd;                                    /* Socket */
                     26:     FILE *             fp;
                     27:     HTInputStream *    input;                               /* Input stream */
                     28:     HTOutputStream *   output;                             /* Output stream */
                     29:     BOOL               active;                 /* Active or passive channel */
                     30:     int                        semaphore;                         /* On channel use */
2.10      frystyk    31:     HTHost *           host;                          /* Zombie connections */
2.1       frystyk    32: };
                     33: 
                     34: struct _HTInputStream {
                     35:     const HTInputStreamClass * isa;    
                     36: };
                     37: 
                     38: struct _HTOutputStream {
                     39:     const HTOutputStreamClass *        isa;    
                     40: };
                     41: 
                     42: PRIVATE HTList ** channels = NULL;                      /* List of channels */
                     43: 
                     44: /* ------------------------------------------------------------------------- */
                     45: 
                     46: PRIVATE void free_channel (HTChannel * ch)
                     47: {
                     48:     if (ch) {
                     49: 
                     50:        /* Close the input and output stream */
2.11      frystyk    51:        if (ch->input) {
                     52:            (*ch->input->isa->close)(ch->input);
                     53:            ch->input = NULL;
                     54:        }
                     55:        if (ch->output) {
                     56:            (*ch->output->isa->close)(ch->output);
                     57:            ch->output = NULL;
                     58:        }
2.1       frystyk    59: 
                     60:        /* Close the socket */
                     61:        if (ch->sockfd != INVSOC) {
                     62:            NETCLOSE(ch->sockfd);
2.12.2.1  eric       63:            /*      HTEvent_unregister(ch->sockfd, all options); */
2.10      frystyk    64:            HTNet_decreaseSocket();
2.1       frystyk    65:            if (PROT_TRACE)
                     66:                HTTrace("Channel..... Deleted %p, socket %d\n", ch,ch->sockfd);
                     67:        }
2.12.2.2  eric       68:        ch->sockfd = INVSOC;
2.1       frystyk    69: 
                     70:        /* Close the file */
                     71:        if (ch->fp) {
                     72:            fclose(ch->fp);
                     73:            if (PROT_TRACE)
                     74:                HTTrace("Channel..... Deleted %p, file %p\n", ch, ch->fp);
                     75:        }
                     76:        HT_FREE(ch);
                     77:     }
                     78: }
                     79: 
                     80: /*
                     81: **     A channel is uniquely identified by a socket.
                     82: **     Note that we don't create the input and output stream - they are 
2.10      frystyk    83: **     created later.
2.1       frystyk    84: **
                     85: **     We only keep a hash on sockfd's as we don't have to look for channels
                     86: **     for ANSI file descriptors.
                     87: */
2.12.2.1  eric       88: PUBLIC HTChannel * HTChannel_new (SOCKET sockfd, BOOL active)
2.1       frystyk    89: {
2.12.2.1  eric       90:     HTList * list = NULL;
                     91:     HTChannel * ch = NULL;
                     92:     int hash = sockfd < 0 ? 0 : HASH(sockfd);
                     93:     if (PROT_TRACE) HTTrace("Channel..... Hash value is %d\n", hash);
                     94:     if (!channels) {
                     95:        if (!(channels = (HTList **) HT_CALLOC(HASH_SIZE,sizeof(HTList*))))
                     96:            HT_OUTOFMEM("HTChannel_new");
2.1       frystyk    97:     }
2.12.2.1  eric       98:     if (!channels[hash]) channels[hash] = HTList_new();
                     99:     list = channels[hash];
                    100:     if ((ch = (HTChannel *) HT_CALLOC(1, sizeof(HTChannel))) == NULL)
                    101:        HT_OUTOFMEM("HTChannel_new");       
                    102:     ch->sockfd = sockfd;
                    103:     ch->active = active;
                    104:     ch->semaphore = 1;
                    105:     HTList_addObject(list, (void *) ch);
                    106: 
                    107:     if (PROT_TRACE) HTTrace("Channel..... Added %p to list %p\n", ch,list);
                    108:     return ch;
2.1       frystyk   109: }
                    110: 
                    111: /*
                    112: **     Look for a channel object if we for some reason should have lost it
                    113: **     Returns NULL if nothing found
                    114: */
                    115: PUBLIC HTChannel * HTChannel_find (SOCKET sockfd)
                    116: {
                    117:     if (channels && sockfd != INVSOC) {
                    118:        int hash = HASH(sockfd);
                    119:        HTList * list = channels[hash];
                    120:        if (list) {
                    121:            HTChannel * ch = NULL;
                    122:            while ((ch = (HTChannel *) HTList_nextObject(list)))
                    123:                if (ch->sockfd == sockfd) return ch;
                    124:        }
                    125:     }
                    126:     return NULL;
                    127: }
                    128: 
                    129: /*
                    130: **     When deleting a channel we first look at if there are no more requests
                    131: **     using the channel (the semaphore is <= 0). Then, if the socket supports
                    132: **     persistent connections then we register the channel in the Host cache
                    133: **     and wait until the other end closes it or we get a time out on our side
                    134: */
2.6       eric      135: PUBLIC BOOL HTChannel_delete (HTChannel * channel, int status)
2.1       frystyk   136: {
                    137:     if (channel) {
2.2       frystyk   138:        if (PROT_TRACE) HTTrace("Channel..... Delete %p with semaphore %d\n",
2.1       frystyk   139:                                channel, channel->semaphore);
                    140:        /*
                    141:        **  We call the free methods on both the input stream and the output
                    142:        **  stream so that we can free up the stream pipes. However, note that
                    143:        **  this doesn't mean that we close the input stream and output stream
                    144:        **  them selves - only the generic streams
                    145:        */
2.12      frystyk   146:        if (status != HT_IGNORE) {
2.12.2.3! eric      147:            if (channel->input) {
2.12      frystyk   148:                if (status == HT_INTERRUPTED)
                    149:                    (*channel->input->isa->abort)(channel->input, NULL);
                    150:                else
                    151:                    (*channel->input->isa->_free)(channel->input);
2.12.2.3! eric      152:                channel->input = NULL;
        !           153:            }
        !           154:            if (channel->output) {
2.12      frystyk   155:                if (status == HT_INTERRUPTED)
                    156:                    (*channel->output->isa->abort)(channel->output, NULL);
                    157:                else
                    158:                    (*channel->output->isa->_free)(channel->output);
2.12.2.3! eric      159:                channel->output = NULL;
        !           160:            }
2.12      frystyk   161:        }
2.1       frystyk   162: 
                    163:        /*
                    164:        **  Check whether this channel is used by other objects or we can
                    165:        **  delete it and free memory.
                    166:        */
2.12.2.2  eric      167:        if (channel->semaphore <= 0 && channels && channel->sockfd != INVSOC) {
2.1       frystyk   168:            int hash = HASH(channel->sockfd);
                    169:            HTList * list = channels[hash];
                    170:            if (list) {
                    171:                HTList_removeObject(list, (void *) channel);
                    172:                free_channel(channel);
                    173:                return YES;
                    174:            }
2.8       frystyk   175:        } else
                    176:            HTChannel_downSemaphore(channel);
2.1       frystyk   177:     }
                    178:     return NO;
                    179: }
                    180: 
                    181: /*     HTChannel_deleteAll
                    182: **     -------------------
                    183: **     Destroys all channels. This is called by HTLibTerminate(0
                    184: */
2.9       frystyk   185: PUBLIC BOOL HTChannel_deleteAll (void)
2.1       frystyk   186: {
                    187:     if (channels) {
                    188:        HTList * cur;
                    189:        int cnt;
                    190:        for (cnt=0; cnt<HASH_SIZE; cnt++) {
                    191:            if ((cur = channels[cnt])) { 
                    192:                HTChannel * pres;
                    193:                while ((pres = (HTChannel *) HTList_nextObject(cur)) != NULL)
                    194:                    free_channel(pres);
                    195:            }
                    196:            HTList_delete(channels[cnt]);
                    197:        }
                    198:        HT_FREE(channels);
                    199:     }
                    200:     return YES;
                    201: }
                    202: 
                    203: /*
2.10      frystyk   204: **     Return the socket associated with this channel
2.1       frystyk   205: */
2.10      frystyk   206: PUBLIC SOCKET HTChannel_socket (HTChannel * channel)
2.1       frystyk   207: {
2.10      frystyk   208:     return channel ? channel->sockfd : INVSOC;
2.1       frystyk   209: }
                    210: 
2.12.2.1  eric      211: PUBLIC void HTChannel_setSocket (HTChannel * channel, SOCKET socket)
                    212: {
                    213:     if (channel)
                    214:       channel->sockfd = socket;
                    215: }
                    216: 
2.10      frystyk   217: /*
                    218: **     Return the file descriptor associated with this channel
                    219: */
                    220: PUBLIC FILE * HTChannel_file (HTChannel * channel)
2.1       frystyk   221: {
2.10      frystyk   222:     return channel ? channel->fp : NULL;
2.1       frystyk   223: }
                    224: 
                    225: /*
2.10      frystyk   226: **     We keep the associated Host object in case we have a
                    227: **     sleeping connection. 
2.1       frystyk   228: */
2.10      frystyk   229: PUBLIC BOOL HTChannel_setHost (HTChannel * ch, HTHost * host)
2.1       frystyk   230: {
2.12.2.1  eric      231:     if (ch) {
2.10      frystyk   232:        ch->host = host;
                    233:        return YES;
                    234:     }
                    235:     return NO;
2.4       frystyk   236: }
                    237: 
2.10      frystyk   238: PUBLIC HTHost * HTChannel_host (HTChannel * ch)
2.4       frystyk   239: {
2.10      frystyk   240:     return (ch ? ch->host : NULL);
2.1       frystyk   241: }
                    242: 
                    243: /*
                    244: **     Increase the semaphore for this channel
                    245: */
                    246: PUBLIC void HTChannel_upSemaphore (HTChannel * channel)
                    247: {
                    248:     if (channel) {
                    249:        channel->semaphore++;
                    250:        if (PROT_TRACE)
                    251:            HTTrace("Channel..... Semaphore increased to %d for channel %p\n",
                    252:                    channel->semaphore, channel);
                    253:     }
                    254: }
                    255: 
                    256: /*
                    257: **     Decrease the semaphore for this channel
                    258: */
                    259: PUBLIC void HTChannel_downSemaphore (HTChannel * channel)
                    260: {
                    261:     if (channel) {
                    262:        channel->semaphore--;
                    263:        if (channel->semaphore <= 0) channel->semaphore = 0;
                    264:        if (PROT_TRACE)
                    265:            HTTrace("Channel..... Semaphore decreased to %d for channel %p\n",
2.7       frystyk   266:                    channel->semaphore, channel);
                    267:     }
                    268: }
                    269: 
                    270: /*
                    271: **     Explicitly set the semaphore for this channel
                    272: */
                    273: PUBLIC void HTChannel_setSemaphore (HTChannel * channel, int semaphore)
                    274: {
                    275:     if (channel) {
                    276:        channel->semaphore = semaphore;
                    277:        if (channel->semaphore <= 0) channel->semaphore = 0;
                    278:        if (PROT_TRACE)
                    279:            HTTrace("Channel..... Semaphore set to %d for channel %p\n",
2.1       frystyk   280:                    channel->semaphore, channel);
                    281:     }
                    282: }
                    283: 
                    284: /*
                    285: **     Create the input stream and bind it to the channel
                    286: **     Please read the description in the HTIOStream module on the parameters
                    287: */
2.10      frystyk   288: PUBLIC BOOL HTChannel_setInput (HTChannel * ch, HTInputStream * input)
2.1       frystyk   289: {
                    290:     if (ch) {
                    291:        ch->input = input;
                    292:        return YES;
                    293:     }
                    294:     return NO;
                    295: }
                    296: 
                    297: PUBLIC HTInputStream * HTChannel_input (HTChannel * ch)
                    298: {
                    299:     return ch ? ch->input : NULL;
                    300: }
                    301: 
                    302: /*
                    303: **     Create the output stream and bind it to the channel
                    304: **     Please read the description in the HTIOStream module on the parameters
                    305: */
2.10      frystyk   306: PUBLIC BOOL HTChannel_setOutput (HTChannel * ch, HTOutputStream * output)
2.1       frystyk   307: {
                    308:     if (ch) {
                    309:        ch->output = output;
                    310:        return YES;
                    311:     }
                    312:     return NO;
                    313: }
                    314: 
                    315: PUBLIC HTOutputStream * HTChannel_output (HTChannel * ch)
                    316: {
                    317:     return ch ? ch->output : NULL;
                    318: }
                    319: 

Webmaster