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

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

Webmaster