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

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:
2.14      frystyk    11: **     12 June 94      Written by Henrik Frystyk, frystyk@w3.org
2.17      frystyk    12: **      31 May  95      Charlie Brooks cbrooks@osf.org
                     13: **
2.1       frystyk    14: */
                     15: 
2.9       frystyk    16: /* Implemention dependent include files */
                     17: #include "tcp.h"
                     18: 
2.1       frystyk    19: /* Library include files */
                     20: #include "HTUtils.h"
                     21: #include "HTAccess.h"
2.16      frystyk    22: #include "HTProt.h"
2.1       frystyk    23: #include "HTError.h"
                     24: #include "HTThread.h"                                   /* Implemented here */
2.17      frystyk    25: #include "HTEvntrg.h"
2.1       frystyk    26: 
2.9       frystyk    27: #ifdef WIN32
                     28: #include <io.h>
                     29: #endif
                     30: 
2.17      frystyk    31: PRIVATE HTList *HTThreads = NULL;               /* List of the HTNetInfo structures */
                     32: PRIVATE fd_set nullSet ;
                     33: PRIVATE fd_set HTfd_intr;
                     34: PRIVATE fd_set HTfd_libs ;
                     35: PRIVATE SOCKET libMaxSock = 0 ;
2.1       frystyk    36: 
                     37: /* ------------------------------------------------------------------------- */
                     38: 
                     39: /*                                                                HTThreadInit
                     40: **
                     41: **     Initiates the thread socket registers. It is very important that
                     42: **     this function is called. It is currently done inside HTAccess in the
                     43: **     HTAccessInit function.
                     44: */
                     45: PUBLIC BOOL HTThreadInit NOARGS
                     46: {
                     47:     static BOOL done=NO;
                     48: 
                     49:     if (done) {
                     50:        if (THD_TRACE)
2.7       frystyk    51:            fprintf(TDEST, "ThreadInit.. Already done\n");
2.1       frystyk    52:        return NO;
                     53:     }
                     54:     done = YES;
2.17      frystyk    55:     FD_ZERO( &HTfd_intr) ;
2.1       frystyk    56:     return YES;
                     57: }
                     58: 
                     59: 
                     60: /*                                                           HTThreadGetFDInfo
                     61: **
                     62: **     Returns the maximum bit width and the read and write bit array.
2.17      frystyk    63: **     N.B. Only used by old HTEvent.c module
2.1       frystyk    64: */
2.17      frystyk    65: 
2.1       frystyk    66: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
                     67: {
2.17      frystyk    68:     *read = nullSet;
                     69:     *write = nullSet;
                     70:     return libMaxSock;
2.1       frystyk    71: }
                     72: 
2.15      frystyk    73: /*                                                      HTThreadStateByRequest
                     74: **
                     75: **     This function registers a socket as waiting for the action given
                     76: **     (read or write etc.). It uses the request structure to find the socket
                     77: */
                     78: PUBLIC void HTThreadStateByRequest ARGS2(HTRequest *, request,
                     79:                                         HTThreadAction, action)
                     80: {
                     81:     if (request && request->net_info && request->net_info->sockfd != INVSOC)
                     82:        HTThreadState(request->net_info->sockfd, action);
                     83: }
                     84: 
2.17      frystyk    85: 
2.20      frystyk    86: /*
                     87: **  LibraryCallback - "glue" between 3.0 thread code and new callback functions
                     88: **  map return codes into a simple yes/no model. 
                     89: */
2.21    ! frystyk    90: PRIVATE int LibraryCallback ARGS3(SOCKET, s, HTRequest *, rq, SockOps, f)
2.20      frystyk    91: {
                     92:     int status = 0 ;
                     93:     HTEventState state ;
                     94:     HTProtocol * proto = (HTProtocol *)
                     95:             HTAnchor_protocol( rq -> anchor) ;
                     96: 
                     97:     /* begin */    
                     98: 
                     99:     if (proto == 0)    /* Whoa! No protocol! */
                    100:        return -1;
                    101:     status = proto->load( rq ) ;
                    102:     if (status != HT_WOULD_BLOCK) {   /* completed - good or bad... */
                    103:         if (THD_TRACE) 
                    104:             fprintf(TDEST, "LibCallBack. Calling Terminate...\n");
                    105:        if (status != HT_OK) {
                    106:            HTLoadTerminate(rq, status);
                    107:            state = HTEventRequestTerminate( rq, status) ;
                    108:            /* if the state isn't EVENT_QUIT */
                    109:            if (! HTEventCheckState( rq, state ))
                    110:                return HT_OK;  /* treat as failure */
                    111:        }
                    112:     }  /* if status */
                    113:     return HT_WOULD_BLOCK;
                    114: }
2.17      frystyk   115: 
2.1       frystyk   116: /*                                                               HTThreadState
                    117: **
                    118: **     This function registers a socket as waiting for the action given
                    119: **     (read or write etc.).
2.17      frystyk   120: **
                    121: **     Charlie Brooks - we handle the interrupt thread state internally to this module 
                    122: **      setting the interrupt on a socket disables it from read/write.
2.1       frystyk   123: */
2.7       frystyk   124: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
2.1       frystyk   125: {
2.17      frystyk   126:     register HTNetInfo * pres ;
                    127:     HTList * cur = HTThreads ;
                    128:     int found = 0 ;
                    129:     HTRequest * reqst ;
                    130: 
2.9       frystyk   131: #ifdef _WIN32
2.17      frystyk   132:        if (sockfd <= 2) 
                    133:                sockfd = _get_osfhandle(sockfd) ;
2.9       frystyk   134: #endif
                    135:   
2.1       frystyk   136:     if (THD_TRACE) {
                    137:        static char *actionmsg[] = {
                    138:            "SET WRITE",
                    139:            "CLEAR WRITE",
                    140:            "SET READ",
                    141:            "CLEAR READ",
2.4       frystyk   142:            "SET INTERRUPT",
                    143:            "CLEAR INTERRUPT",
2.17      frystyk   144:            "CLOSE",
                    145:            "SET CONNECT",
                    146:            "CLEAR CONNECT"
2.1       frystyk   147:            };
2.7       frystyk   148:        fprintf(TDEST,
2.17      frystyk   149:                "Thread...... Registering socket number %d for action %s\n",
2.1       frystyk   150:                sockfd, *(actionmsg+action));
2.17      frystyk   151:     }   /* if */
                    152: 
                    153:     FD_SET( sockfd, &HTfd_libs) ;
                    154:     if (libMaxSock < sockfd)
                    155:        libMaxSock = sockfd ;
                    156: 
                    157: 
                    158:     while ((pres = (HTNetInfo *)HTList_nextObject(cur) ) != 0) { 
                    159:         if (pres->sockfd == sockfd) {
                    160:             found = 1 ;
                    161:             break ;
                    162:         }   /* if */
                    163:     }       /* while */
                    164: 
                    165:     if (! found)    /* how'd you get here? */
                    166:         return ;
                    167: 
                    168:     reqst = pres->request ;
2.1       frystyk   169:     switch (action) {
                    170:       case THD_SET_WRITE:
2.17      frystyk   171:       case THD_SET_CONNECT: 
                    172:         HTEvent_Register( sockfd, reqst, action == THD_SET_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT , 
                    173:                LibraryCallback, 0);
2.1       frystyk   174:        break;
                    175: 
                    176:       case THD_CLR_WRITE:
2.17      frystyk   177:       case THD_CLR_CONNECT: 
                    178:         HTEvent_UnRegister( sockfd, action == THD_CLR_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT) ;
2.1       frystyk   179:        break;
                    180: 
                    181:       case THD_SET_READ:
2.17      frystyk   182:         HTEvent_Register( sockfd, reqst, (SockOps)FD_READ, LibraryCallback, 0);  
2.1       frystyk   183:        break;
                    184: 
                    185:       case THD_CLR_READ:
2.17      frystyk   186:         HTEvent_UnRegister( sockfd, FD_WRITE) ;
2.1       frystyk   187:        break;
                    188: 
                    189:       case THD_CLOSE:
2.17      frystyk   190:         HTEvent_UnRegister( sockfd, FD_ALL) ;
                    191:        FD_CLR( sockfd, &HTfd_libs);
                    192:        FD_CLR( sockfd, &HTfd_intr);
                    193:        libMaxSock = 0 ;
                    194:        while ((pres = (HTNetInfo *)HTList_nextObject(cur) ) != 0) { 
                    195:            if (pres->sockfd > libMaxSock) {
                    196:                libMaxSock = sockfd ;
                    197:            }   /* if */
                    198:        }       /* while */
                    199: 
2.1       frystyk   200:        break;
                    201: 
2.17      frystyk   202: /*
                    203:  * we handle interrupts locally ... only library sockets can 
                    204:  * be interrupted? 
                    205:  */
                    206: 
2.2       frystyk   207:       case THD_SET_INTR:
2.17      frystyk   208:         HTEvent_UnRegister( sockfd, (SockOps)(FD_READ | FD_WRITE) );
                    209:         FD_SET( sockfd, &HTfd_intr) ;
2.1       frystyk   210:        break;
                    211: 
2.2       frystyk   212:       case THD_CLR_INTR:
2.17      frystyk   213:         FD_CLR( sockfd, &HTfd_intr) ;
                    214:        HTEvent_UnRegister(sockfd, FD_ALL) ;  /* no sin to unregister and unregistered socket */
2.2       frystyk   215:        break;
                    216: 
2.1       frystyk   217:       default:
                    218:        if (THD_TRACE)
2.17      frystyk   219:            fprintf(TDEST, "Thread...... Illegal socket action (%d)\n", (int)action);
2.1       frystyk   220:     }
2.17      frystyk   221:     return ;
2.1       frystyk   222: }
                    223: 
                    224: 
                    225: /*                                                                HTThreadIntr
                    226: **
                    227: **     This function returns YES or NO to the question
                    228: */
2.7       frystyk   229: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
2.1       frystyk   230: {
                    231:     return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
                    232: }
                    233: 
                    234: 
                    235: /*                                                         HTThreadMarkIntrAll
                    236: **
2.2       frystyk   237: **     Marks all Library sockets as interrupted. User sockets can not be
2.17      frystyk   238: **     interrupted
2.1       frystyk   239: */
2.17      frystyk   240: PUBLIC BOOL HTThreadMarkIntrAll( CONST fd_set * fd_user )
2.1       frystyk   241: {
2.12      frystyk   242:     HTNetInfo *pres;
                    243:     if (HTThreads) {
                    244:        while ((pres = (HTNetInfo *) HTList_lastObject(HTThreads)) != NULL)
                    245:            HTThread_kill(pres);
                    246:        return YES;
                    247:     }
                    248:     return NO;
                    249: 
2.1       frystyk   250: }
                    251: 
                    252: 
                    253: /*                                                              HTThreadActive
                    254: **
                    255: **     Returns yes as long as a socket other than stdin is registered in 
                    256: **     the total set of sockets.
                    257: */
                    258: PUBLIC BOOL HTThreadActive NOARGS
                    259: {
2.17      frystyk   260:     if (libMaxSock > 0)
                    261:        return YES; 
                    262:     else 
                    263:        return NO;
2.1       frystyk   264: }
                    265: 
                    266: 
                    267: /*                                                                HTThread_new
                    268: **
                    269: **     Register the HTNetInfo structure in a list so that we can find the 
2.17      frystyk   270: **     request which corresponds to a socket descriptor
2.1       frystyk   271: */
2.12      frystyk   272: PUBLIC BOOL HTThread_new ARGS1(HTNetInfo *, new_net)
2.1       frystyk   273: {
                    274:     if (!HTThreads)
2.17      frystyk   275:                HTThreads = HTList_new();
2.12      frystyk   276:     return HTList_addObject(HTThreads, (void *) new_net);
2.1       frystyk   277: }
                    278: 
                    279: 
                    280: /*                                                              HTThread_clear
                    281: **
2.17      frystyk   282: **     Remove the HTNetInfo from the list of acrive threads.
2.1       frystyk   283: */
2.12      frystyk   284: PUBLIC BOOL HTThread_clear ARGS1(HTNetInfo *, old_net)
2.1       frystyk   285: {
                    286:     if (HTThreads)
                    287:        return HTList_removeObject(HTThreads, (void *) old_net);
                    288:     return NO;
                    289: }
                    290: 
2.17      frystyk   291: /*                                                           HTThread_isAlive
                    292: **
                    293: **     Checks whether a thread is still registered and if so returns the 
                    294: **     corresponding HTRequest structure, else return NULL.
                    295: */
                    296: PUBLIC HTRequest *HTThread_isAlive ARGS1(HTNetInfo *, net)
                    297: {
                    298:     HTList *cur = HTThreads;
                    299:     HTNetInfo *pres;
                    300:     if (cur && net) {
                    301:        while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
                    302:            if (pres == net) return pres->request;
                    303:        }
                    304:     }
                    305:     if (THD_TRACE)
                    306:        fprintf(TDEST, "Thread...... Thread is not alive\n");
                    307:     return NULL;
                    308: }
2.1       frystyk   309: 
2.12      frystyk   310: /*                                                              HTThread_kill
                    311: **
                    312: **     Kill the thread and remove the HTNetInfo from the list of active
                    313: **     threads.
                    314: **     Returns YES on success, NO on error
                    315: **
                    316: **     BUG: We do not take ANSI C file descriptors into account
                    317: */
2.17      frystyk   318: 
2.12      frystyk   319: PUBLIC BOOL HTThread_kill ARGS1(HTNetInfo *, kill_net)
                    320: {
2.17      frystyk   321:     if (HTThreads) {
2.12      frystyk   322:        HTList *cur = HTThreads;
                    323:        HTNetInfo *pres;
                    324: 
                    325:        /* Find the corresponding HTRequest structure */
                    326:        while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
                    327:            if (pres == kill_net) break;
                    328:        }
                    329: 
                    330:        /*
                    331:        **  Now see if a socket is active (or an ANSI C file descriptor).
                    332:        **  If so then mark the thread as interrupted and call the load
                    333:        **  function.
                    334:        */
                    335:        if (pres) {
                    336:            if (kill_net->sockfd != INVSOC) {     /* @@@ ANSI C FIlE DES @@@ */
                    337:                HTProtocol *prot = (HTProtocol *)
                    338:                    HTAnchor_protocol(kill_net->request->anchor);
                    339:                HTThreadState(kill_net->sockfd, THD_SET_INTR);
                    340:                (*(prot->load))(kill_net->request);
                    341:            }
                    342:            return HTThread_clear(kill_net);
2.17      frystyk   343:        } else {
                    344:            if (THD_TRACE)
                    345:                fprintf(TDEST, "Kill Thread. Thread is not registered\n");
                    346:            return NO;
2.12      frystyk   347:        }
                    348:     }
                    349:     return NO;
2.13      frystyk   350: }

Webmaster