Annotation of libwww/Library/src/HTNet.c, revision 2.10.2.1

2.10.2.1! cbrooks     1: /*                                                                  HTThread.c
        !             2: **     MULTIPLE THREAD SOCKET MANAGEMENT
        !             3: **
        !             4: **     (c) COPYRIGHT MIT 1995.
        !             5: **     Please first read the full copyright statement in the file COPYRIGH.
        !             6: **
        !             7: **     This is the implementation of the internal library multithreading
        !             8: **     functions. This includes an interrupt handler and a event loop.
        !             9: **     
        !            10: ** History:
        !            11: **     12 June 94      Written by Henrik Frystyk, frystyk@dxcern.cern.ch
        !            12: */
        !            13: 
        !            14: /* Implemention dependent include files */
        !            15: #include "tcp.h"
        !            16: 
        !            17: /* Library include files */
        !            18: #include "HTUtils.h"
        !            19: #include "HTAccess.h"
        !            20: #include "HTError.h"
        !            21: #include "HTThread.h"                                   /* Implemented here */
        !            22: 
        !            23: #ifdef WIN32
        !            24: #include <io.h>
        !            25: #endif
        !            26: 
        !            27: /* Type definitions and global variables etc. local to this module */
        !            28: PRIVATE fd_set HTfd_read;            /* Bit array of sockets ready for read */
        !            29: PRIVATE fd_set HTfd_write;          /* Bit array of sockets ready for write */
        !            30: PRIVATE int    HTMaxfdpl = 0;                  /* Max number of sockets + 1 */
        !            31: 
        !            32: PRIVATE fd_set HTfd_intr;              /* All sockets currently interrupted */
        !            33: PRIVATE fd_set HTfd_set;                /* All sockets currently registered */
        !            34: 
        !            35: 
        !            36: PRIVATE HTList *HTThreads = NULL;               /* List of the HTNetInfo structures */
        !            37: 
        !            38: /* ------------------------------------------------------------------------- */
        !            39: 
        !            40: /*                                                                HTThreadInit
        !            41: **
        !            42: **     Initiates the thread socket registers. It is very important that
        !            43: **     this function is called. It is currently done inside HTAccess in the
        !            44: **     HTAccessInit function.
        !            45: */
        !            46: PUBLIC BOOL HTThreadInit NOARGS
        !            47: {
        !            48:     static BOOL done=NO;
        !            49: 
        !            50:     if (done) {
        !            51:        if (THD_TRACE)
        !            52:            fprintf(TDEST, "ThreadInit.. Already done\n");
        !            53:        return NO;
        !            54:     }
        !            55:     done = YES;
        !            56: 
        !            57:     /* Initialize the other internal bit arrays */
        !            58:     FD_ZERO(&HTfd_write);
        !            59:     FD_ZERO(&HTfd_set);
        !            60:     FD_ZERO(&HTfd_intr);
        !            61:        FD_ZERO(&HTfd_read) ;
        !            62: 
        !            63:     return YES;
        !            64: }
        !            65: 
        !            66: 
        !            67: /*                                                           HTThreadGetFDInfo
        !            68: **
        !            69: **     Returns the maximum bit width and the read and write bit array.
        !            70: */
        !            71: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
        !            72: {
        !            73:     *read = HTfd_read;
        !            74:     *write = HTfd_write;
        !            75:     return HTMaxfdpl;
        !            76: }
        !            77: 
        !            78: 
        !            79: /*                                                               HTThreadState
        !            80: **
        !            81: **     This function registers a socket as waiting for the action given
        !            82: **     (read or write etc.).
        !            83: */
        !            84: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
        !            85: {
        !            86: #ifdef _WIN32
        !            87:        if (sockfd <= 2) 
        !            88:                sockfd = _get_osfhandle(sockfd) ;
        !            89: #endif
        !            90:   
        !            91:     if (THD_TRACE) {
        !            92:        static char *actionmsg[] = {
        !            93:            "SET WRITE",
        !            94:            "CLEAR WRITE",
        !            95:            "SET READ",
        !            96:            "CLEAR READ",
        !            97:            "SET INTERRUPT",
        !            98:            "CLEAR INTERRUPT",
        !            99:            "CLOSE"
        !           100:            };
        !           101:        fprintf(TDEST,
        !           102:                "Thread...... Register socket number %d for action %s\n",
        !           103:                sockfd, *(actionmsg+action));
        !           104:     }
        !           105:     switch (action) {
        !           106:       case THD_SET_WRITE:
        !           107:        FD_CLR(sockfd, &HTfd_read);
        !           108:        if (! FD_ISSET(sockfd, &HTfd_write))
        !           109:                FD_SET(sockfd, &HTfd_write);
        !           110:        if (! FD_ISSET(sockfd, &HTfd_set))
        !           111:                FD_SET(sockfd, &HTfd_set);
        !           112:        break;
        !           113: 
        !           114:       case THD_CLR_WRITE:
        !           115:        FD_CLR(sockfd, &HTfd_read);
        !           116:        FD_CLR(sockfd, &HTfd_write);
        !           117:        FD_CLR(sockfd, &HTfd_set);
        !           118:        break;
        !           119: 
        !           120:       case THD_SET_READ:
        !           121:        if (! FD_ISSET(sockfd, &HTfd_read))
        !           122:                FD_SET(sockfd, &HTfd_read);
        !           123:        FD_CLR(sockfd, &HTfd_write);
        !           124:        if (! FD_ISSET(sockfd, &HTfd_set))
        !           125:                FD_SET(sockfd, &HTfd_set);
        !           126:        break;
        !           127: 
        !           128:       case THD_CLR_READ:
        !           129:        FD_CLR(sockfd, &HTfd_read);
        !           130:        FD_CLR(sockfd, &HTfd_write);
        !           131:        FD_CLR(sockfd, &HTfd_set);
        !           132:        break;
        !           133: 
        !           134:       case THD_CLOSE:
        !           135:        FD_CLR(sockfd, &HTfd_read);
        !           136:        FD_CLR(sockfd, &HTfd_write);
        !           137:        FD_CLR(sockfd, &HTfd_intr);
        !           138:        FD_CLR(sockfd, &HTfd_set);
        !           139:        break;
        !           140: 
        !           141:       case THD_SET_INTR:
        !           142:        FD_CLR(sockfd, &HTfd_read);
        !           143:        FD_CLR(sockfd, &HTfd_write);
        !           144:        if (! FD_ISSET(sockfd, &HTfd_intr))
        !           145:                FD_SET(sockfd, &HTfd_intr);
        !           146:        break;
        !           147: 
        !           148:       case THD_CLR_INTR:
        !           149:        FD_CLR(sockfd, &HTfd_intr);
        !           150:        break;
        !           151: 
        !           152:       default:
        !           153:        if (THD_TRACE)
        !           154:            fprintf(TDEST, "Thread...... Illigal socket action\n");
        !           155:     }
        !           156: 
        !           157:     /* Update max bit width. The method used ignores any other default
        !           158:        opened file descriptors between 0 and the actual set of file
        !           159:        descriptors used. However, they are not registered anyway */
        !           160: 
        !           161:     if (action == THD_CLOSE) {
        !           162: #ifdef _WINSOCKAPI_
        !           163:        HTMaxfdpl = HTfd_set.fd_count ;
        !           164: #else 
        !           165:        if (sockfd+1 >= HTMaxfdpl) {
        !           166:            while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
        !           167:                HTMaxfdpl--;
        !           168:        }
        !           169: #endif
        !           170:     } else {
        !           171: #ifdef _WINSOCKAPI_
        !           172:        HTMaxfdpl = HTfd_set.fd_count;
        !           173: #else
        !           174:        if (sockfd+1 > HTMaxfdpl)
        !           175:            HTMaxfdpl = sockfd+1;
        !           176: #endif 
        !           177:     }
        !           178:     if (THD_TRACE)
        !           179:        fprintf(TDEST, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
        !           180: }
        !           181: 
        !           182: 
        !           183: /*                                                                HTThreadIntr
        !           184: **
        !           185: **     This function returns YES or NO to the question
        !           186: */
        !           187: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
        !           188: {
        !           189:     return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
        !           190: }
        !           191: 
        !           192: 
        !           193: /*                                                         HTThreadMarkIntrAll
        !           194: **
        !           195: **     Marks all Library sockets as interrupted. User sockets can not be
        !           196: **     interrupted
        !           197: */
        !           198: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *,  fd_user)
        !           199: {
        !           200:     int cnt;
        !           201: #ifdef _WINSOCKAPI_
        !           202:     int i;
        !           203: #endif
        !           204:     if (THD_TRACE)
        !           205:        fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
        !           206: #ifdef _WINSOCKAPI_
        !           207:     for (i = 0 ; i < HTfd_set.fd_count; i++) {
        !           208:        cnt = HTfd_set.fd_array[i];
        !           209:        if (!FD_ISSET(cnt, fd_user))
        !           210: #else
        !           211:     for (cnt=0; cnt<HTMaxfdpl; cnt++) {
        !           212:        if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
        !           213: #endif
        !           214:            FD_SET(cnt, &HTfd_intr);
        !           215:     }
        !           216: }
        !           217: 
        !           218: 
        !           219: /*                                                              HTThreadActive
        !           220: **
        !           221: **     Returns yes as long as a socket other than stdin is registered in 
        !           222: **     the total set of sockets.
        !           223: */
        !           224: PUBLIC BOOL HTThreadActive NOARGS
        !           225: {
        !           226:     int cnt;
        !           227: #ifdef _WINSOCKAPI_
        !           228:     if (HTfd_set.fd_count > 0)
        !           229:        return YES;
        !           230: #else
        !           231:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
        !           232:        if (FD_ISSET(cnt, &HTfd_set))
        !           233:            return YES;
        !           234: #endif
        !           235:     return NO;
        !           236: }
        !           237: 
        !           238: 
        !           239: /*                                                                HTThread_new
        !           240: **
        !           241: **     Register the HTNetInfo structure in a list so that we can find the 
        !           242: **     request which corresponds to a socket descriptor
        !           243: */
        !           244: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
        !           245: {
        !           246:     if (!HTThreads)
        !           247:        HTThreads = HTList_new();
        !           248:     HTList_addObject(HTThreads, (void *) new_net);
        !           249: }
        !           250: 
        !           251: 
        !           252: /*                                                              HTThread_clear
        !           253: **
        !           254: **     Remove the HTNetInfo from the list of acrive threads.
        !           255: */
        !           256: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
        !           257: {
        !           258:     if (HTThreads)
        !           259:        return HTList_removeObject(HTThreads, (void *) old_net);
        !           260:     return NO;
        !           261: }
        !           262: 
        !           263: 
        !           264: /*                                                        HTThread_getCallBack
        !           265: **
        !           266: **     Finds a socket and makes it the active thread. READ has a higher
        !           267: **     priority than WRITE as it might influence (stop) the WRITE process.
        !           268: **     Returns the request structure of the active thread, NULL on error.
        !           269: **     A interrupted socket has the highest priority
        !           270: */
        !           271: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *,    fd_read,
        !           272:                                            CONST fd_set *,     fd_write)
        !           273: {
        !           274:     HTList *cur = HTThreads;
        !           275:     HTNetInfo *pres;
        !           276:     SOCKFD cnt;
        !           277:     SocAction found = SOC_INVALID;
        !           278: 
        !           279: #ifdef _WINSOCKAPI_
        !           280:     int ic = 0;
        !           281: #endif
        !           282: 
        !           283: #ifdef _WINSOCKAPI_
        !           284:     for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic];
        !           285: #else
        !           286:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
        !           287: #endif
        !           288:        if (FD_ISSET(cnt, &HTfd_intr)) {
        !           289:            if (THD_TRACE)
        !           290:                fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
        !           291:            found = SOC_INTERRUPT;
        !           292:            break;
        !           293:        }
        !           294:     }
        !           295: 
        !           296:     if (found == SOC_INVALID) {
        !           297: #ifdef _WINSOCKAPI_
        !           298:        for (ic = 0; ic < HTfd_set.fd_count; ic++) {
        !           299:            cnt = HTfd_set.fd_array[ic]; 
        !           300: #else
        !           301:        for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {             /* READ */
        !           302: #endif
        !           303:            if (FD_ISSET(cnt, fd_read)) {
        !           304:                if (THD_TRACE)
        !           305:                    fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
        !           306:                found = SOC_READ;
        !           307:                break;
        !           308:            }
        !           309:        }
        !           310:     }
        !           311: 
        !           312:     if (found == SOC_INVALID) {
        !           313: #ifdef _WINSOCKAPI_
        !           314:        for (ic = 0; ic < HTfd_set.fd_count; ic++) {
        !           315:            cnt = HTfd_set.fd_array[ic]; 
        !           316: #else
        !           317:         for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* WRITE */
        !           318: #endif
        !           319:            if (FD_ISSET(cnt, fd_write)) {
        !           320:                if (THD_TRACE)
        !           321:                    fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
        !           322:                found = SOC_WRITE;
        !           323:                break;
        !           324:            }
        !           325:        }
        !           326:     }
        !           327: 
        !           328:     if (found == SOC_INVALID || cur == NULL)
        !           329:        return NULL;
        !           330: 
        !           331:     /* Find the corresponding HTNetInfo and HTRequest structure */
        !           332:     while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
        !           333:        if (pres->sockfd == cnt) {
        !           334:            pres->action = found;
        !           335:            return pres->request;
        !           336:        }
        !           337:     }
        !           338:     return NULL;
        !           339: }
        !           340: 

Webmaster