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

2.4       frystyk     1: /*                                                                  HTThread.c
                      2: **     MULTIPLE THREAD SOCKET MANAGEMENT
2.1       frystyk     3: **
2.10      frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.4       frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **     This is the implementation of the internal library multithreading
2.1       frystyk     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: 
2.9       frystyk    14: /* Implemention dependent include files */
                     15: #include "tcp.h"
                     16: 
2.1       frystyk    17: /* Library include files */
                     18: #include "HTUtils.h"
                     19: #include "HTAccess.h"
                     20: #include "HTError.h"
                     21: #include "HTThread.h"                                   /* Implemented here */
                     22: 
2.9       frystyk    23: #ifdef WIN32
                     24: #include <io.h>
                     25: #endif
                     26: 
2.1       frystyk    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: 
2.9       frystyk    35: 
2.1       frystyk    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)
2.7       frystyk    52:            fprintf(TDEST, "ThreadInit.. Already done\n");
2.1       frystyk    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);
2.9       frystyk    61:        FD_ZERO(&HTfd_read) ;
                     62: 
2.1       frystyk    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: */
2.7       frystyk    84: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
2.1       frystyk    85: {
2.9       frystyk    86: #ifdef _WIN32
2.12    ! frystyk    87:     if (sockfd <= 2)
        !            88:        sockfd = _get_osfhandle(sockfd);
2.9       frystyk    89: #endif
                     90:   
2.1       frystyk    91:     if (THD_TRACE) {
                     92:        static char *actionmsg[] = {
                     93:            "SET WRITE",
                     94:            "CLEAR WRITE",
                     95:            "SET READ",
                     96:            "CLEAR READ",
2.4       frystyk    97:            "SET INTERRUPT",
                     98:            "CLEAR INTERRUPT",
2.1       frystyk    99:            "CLOSE"
                    100:            };
2.7       frystyk   101:        fprintf(TDEST,
2.1       frystyk   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);
2.12    ! frystyk   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);
2.1       frystyk   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:
2.12    ! frystyk   121:        if (!FD_ISSET(sockfd, &HTfd_read))
        !           122:            FD_SET(sockfd, &HTfd_read);
2.1       frystyk   123:        FD_CLR(sockfd, &HTfd_write);
2.12    ! frystyk   124:        if (!FD_ISSET(sockfd, &HTfd_set))
        !           125:            FD_SET(sockfd, &HTfd_set);
2.1       frystyk   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: 
2.2       frystyk   141:       case THD_SET_INTR:
2.1       frystyk   142:        FD_CLR(sockfd, &HTfd_read);
                    143:        FD_CLR(sockfd, &HTfd_write);
2.12    ! frystyk   144:        if (!FD_ISSET(sockfd, &HTfd_intr))
        !           145:            FD_SET(sockfd, &HTfd_intr);
2.1       frystyk   146:        break;
                    147: 
2.2       frystyk   148:       case THD_CLR_INTR:
                    149:        FD_CLR(sockfd, &HTfd_intr);
                    150:        break;
                    151: 
2.1       frystyk   152:       default:
                    153:        if (THD_TRACE)
2.7       frystyk   154:            fprintf(TDEST, "Thread...... Illigal socket action\n");
2.1       frystyk   155:     }
                    156: 
                    157:     /* Update max bit width. The method used ignores any other default
2.2       frystyk   158:        opened file descriptors between 0 and the actual set of file
                    159:        descriptors used. However, they are not registered anyway */
2.9       frystyk   160: 
2.1       frystyk   161:     if (action == THD_CLOSE) {
2.9       frystyk   162: #ifdef _WINSOCKAPI_
                    163:        HTMaxfdpl = HTfd_set.fd_count ;
                    164: #else 
2.1       frystyk   165:        if (sockfd+1 >= HTMaxfdpl) {
2.2       frystyk   166:            while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
2.1       frystyk   167:                HTMaxfdpl--;
                    168:        }
2.9       frystyk   169: #endif
2.1       frystyk   170:     } else {
2.9       frystyk   171: #ifdef _WINSOCKAPI_
                    172:        HTMaxfdpl = HTfd_set.fd_count;
                    173: #else
2.1       frystyk   174:        if (sockfd+1 > HTMaxfdpl)
                    175:            HTMaxfdpl = sockfd+1;
2.9       frystyk   176: #endif 
2.1       frystyk   177:     }
                    178:     if (THD_TRACE)
2.7       frystyk   179:        fprintf(TDEST, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
2.1       frystyk   180: }
                    181: 
                    182: 
                    183: /*                                                                HTThreadIntr
                    184: **
                    185: **     This function returns YES or NO to the question
                    186: */
2.7       frystyk   187: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
2.1       frystyk   188: {
                    189:     return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
                    190: }
                    191: 
                    192: 
                    193: /*                                                         HTThreadMarkIntrAll
                    194: **
2.2       frystyk   195: **     Marks all Library sockets as interrupted. User sockets can not be
2.12    ! frystyk   196: **     interrupted.
2.1       frystyk   197: */
2.12    ! frystyk   198: PUBLIC BOOL HTThreadMarkIntrAll ARGS1(CONST fd_set *, fd_user)
2.1       frystyk   199: {
2.12    ! frystyk   200:     HTNetInfo *pres;
        !           201:     if (HTThreads) {
        !           202:        while ((pres = (HTNetInfo *) HTList_lastObject(HTThreads)) != NULL)
        !           203:            HTThread_kill(pres);
        !           204:        return YES;
        !           205:     }
        !           206:     return NO;
        !           207: 
        !           208: #if 0
        !           209:     /*
        !           210:     ** Use the HTThread list instead of the bit arrays. This makes it easier
        !           211:     ** to execute a kill thread right away
        !           212:     */
2.1       frystyk   213:     int cnt;
2.9       frystyk   214: #ifdef _WINSOCKAPI_
                    215:     int i;
                    216: #endif
2.1       frystyk   217:     if (THD_TRACE)
2.7       frystyk   218:        fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
2.9       frystyk   219: #ifdef _WINSOCKAPI_
                    220:     for (i = 0 ; i < HTfd_set.fd_count; i++) {
                    221:        cnt = HTfd_set.fd_array[i];
                    222:        if (!FD_ISSET(cnt, fd_user))
                    223: #else
2.2       frystyk   224:     for (cnt=0; cnt<HTMaxfdpl; cnt++) {
2.4       frystyk   225:        if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
2.9       frystyk   226: #endif
2.4       frystyk   227:            FD_SET(cnt, &HTfd_intr);
2.2       frystyk   228:     }
2.12    ! frystyk   229: #endif
2.1       frystyk   230: }
                    231: 
                    232: 
                    233: /*                                                              HTThreadActive
                    234: **
                    235: **     Returns yes as long as a socket other than stdin is registered in 
                    236: **     the total set of sockets.
                    237: */
                    238: PUBLIC BOOL HTThreadActive NOARGS
                    239: {
                    240:     int cnt;
2.9       frystyk   241: #ifdef _WINSOCKAPI_
                    242:     if (HTfd_set.fd_count > 0)
                    243:        return YES;
                    244: #else
2.1       frystyk   245:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
                    246:        if (FD_ISSET(cnt, &HTfd_set))
                    247:            return YES;
2.9       frystyk   248: #endif
2.1       frystyk   249:     return NO;
                    250: }
                    251: 
                    252: 
                    253: /*                                                                HTThread_new
                    254: **
                    255: **     Register the HTNetInfo structure in a list so that we can find the 
2.12    ! frystyk   256: **     request which corresponds to a socket descriptor.
        !           257: **     Returns YES on success, NO on error
2.1       frystyk   258: */
2.12    ! frystyk   259: PUBLIC BOOL HTThread_new ARGS1(HTNetInfo *, new_net)
2.1       frystyk   260: {
                    261:     if (!HTThreads)
                    262:        HTThreads = HTList_new();
2.12    ! frystyk   263:     return HTList_addObject(HTThreads, (void *) new_net);
2.1       frystyk   264: }
                    265: 
                    266: 
                    267: /*                                                              HTThread_clear
                    268: **
2.12    ! frystyk   269: **     Remove the HTNetInfo from the list of active threads.
        !           270: **     Returns YES on success, NO on error
2.1       frystyk   271: */
2.12    ! frystyk   272: PUBLIC BOOL HTThread_clear ARGS1(HTNetInfo *, old_net)
2.1       frystyk   273: {
                    274:     if (HTThreads)
                    275:        return HTList_removeObject(HTThreads, (void *) old_net);
                    276:     return NO;
                    277: }
                    278: 
                    279: 
2.12    ! frystyk   280: /*                                                              HTThread_kill
        !           281: **
        !           282: **     Kill the thread and remove the HTNetInfo from the list of active
        !           283: **     threads.
        !           284: **     Returns YES on success, NO on error
        !           285: **
        !           286: **     BUG: We do not take ANSI C file descriptors into account
        !           287: */
        !           288: PUBLIC BOOL HTThread_kill ARGS1(HTNetInfo *, kill_net)
        !           289: {
        !           290:     if (HTThreads) {
        !           291:        HTList *cur = HTThreads;
        !           292:        HTNetInfo *pres;
        !           293: 
        !           294:        /* Find the corresponding HTRequest structure */
        !           295:        while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
        !           296:            if (pres == kill_net) break;
        !           297:        }
        !           298: 
        !           299:        /*
        !           300:        **  Now see if a socket is active (or an ANSI C file descriptor).
        !           301:        **  If so then mark the thread as interrupted and call the load
        !           302:        **  function.
        !           303:        */
        !           304:        if (pres) {
        !           305:            if (kill_net->sockfd != INVSOC) {     /* @@@ ANSI C FIlE DES @@@ */
        !           306:                HTProtocol *prot = (HTProtocol *)
        !           307:                    HTAnchor_protocol(kill_net->request->anchor);
        !           308:                HTThreadState(kill_net->sockfd, THD_SET_INTR);
        !           309:                (*(prot->load))(kill_net->request);
        !           310:            }
        !           311:            return HTThread_clear(kill_net);
        !           312:        } else {
        !           313:            if (THD_TRACE)
        !           314:                fprintf(TDEST, "Kill Thread. Thread is not registered\n");
        !           315:            return NO;
        !           316:        }
        !           317:     }
        !           318:     return NO;
        !           319: }
        !           320: 
        !           321: 
2.1       frystyk   322: /*                                                        HTThread_getCallBack
                    323: **
                    324: **     Finds a socket and makes it the active thread. READ has a higher
                    325: **     priority than WRITE as it might influence (stop) the WRITE process.
                    326: **     Returns the request structure of the active thread, NULL on error.
                    327: **     A interrupted socket has the highest priority
                    328: */
                    329: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *,    fd_read,
                    330:                                            CONST fd_set *,     fd_write)
                    331: {
2.7       frystyk   332:     SOCKFD cnt;
2.8       frystyk   333:     SocAction found = SOC_INVALID;
2.9       frystyk   334: 
                    335: #ifdef _WINSOCKAPI_
                    336:     int ic = 0;
                    337: #endif
                    338: 
2.12    ! frystyk   339: #if 0
        !           340: 
        !           341: /* Should not be necessary after we have HTThread_kill() */
2.9       frystyk   342: #ifdef _WINSOCKAPI_
2.12    ! frystyk   343:     for (ic = 0; ic < HTfd_set.fd_count; ic++) {
        !           344:        cnt = HTfd_set.fd_array[ic];
2.9       frystyk   345: #else
2.1       frystyk   346:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
2.9       frystyk   347: #endif
2.1       frystyk   348:        if (FD_ISSET(cnt, &HTfd_intr)) {
                    349:            if (THD_TRACE)
2.7       frystyk   350:                fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
2.8       frystyk   351:            found = SOC_INTERRUPT;
2.1       frystyk   352:            break;
                    353:        }
                    354:     }
2.9       frystyk   355: 
2.12    ! frystyk   356: #endif
        !           357: 
2.8       frystyk   358:     if (found == SOC_INVALID) {
2.9       frystyk   359: #ifdef _WINSOCKAPI_
                    360:        for (ic = 0; ic < HTfd_set.fd_count; ic++) {
                    361:            cnt = HTfd_set.fd_array[ic]; 
                    362: #else
2.1       frystyk   363:        for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {             /* READ */
2.9       frystyk   364: #endif
2.1       frystyk   365:            if (FD_ISSET(cnt, fd_read)) {
                    366:                if (THD_TRACE)
2.7       frystyk   367:                    fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
2.8       frystyk   368:                found = SOC_READ;
2.1       frystyk   369:                break;
                    370:            }
                    371:        }
                    372:     }
2.9       frystyk   373: 
2.8       frystyk   374:     if (found == SOC_INVALID) {
2.9       frystyk   375: #ifdef _WINSOCKAPI_
                    376:        for (ic = 0; ic < HTfd_set.fd_count; ic++) {
                    377:            cnt = HTfd_set.fd_array[ic]; 
                    378: #else
                    379:         for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* WRITE */
                    380: #endif
2.1       frystyk   381:            if (FD_ISSET(cnt, fd_write)) {
                    382:                if (THD_TRACE)
2.7       frystyk   383:                    fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
2.8       frystyk   384:                found = SOC_WRITE;
2.1       frystyk   385:                break;
                    386:            }
                    387:        }
                    388:     }
2.9       frystyk   389: 
2.12    ! frystyk   390:     if (found == SOC_INVALID)
2.1       frystyk   391:        return NULL;
                    392: 
2.8       frystyk   393:     /* Find the corresponding HTNetInfo and HTRequest structure */
2.12    ! frystyk   394:     {
        !           395:        HTList *cur = HTThreads;
        !           396:        HTNetInfo *pres;
        !           397:        if (cur) {
        !           398:            while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
        !           399:                if (pres->sockfd == cnt) {
        !           400:                    pres->action = found;
        !           401:                    return pres->request;
        !           402:                }
        !           403:            }
2.1       frystyk   404:        }
                    405:     }
                    406:     return NULL;
                    407: }
2.9       frystyk   408: 

Webmaster