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

2.23    ! frystyk     1: /*                                                                  HTNet.c
        !             2: **     ASYNCRONOUS 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"
2.16      frystyk    21: #include "HTProt.h"
2.1       frystyk    22: #include "HTError.h"
2.23    ! frystyk    23: #include "HTReqMan.h"
2.17      frystyk    24: #include "HTEvntrg.h"
2.23    ! frystyk    25: #include "HTStream.h"
        !            26: #include "HTNet.h"                                      /* Implemented here */
2.1       frystyk    27: 
2.9       frystyk    28: #ifdef WIN32
                     29: #include <io.h>
                     30: #endif
                     31: 
2.23    ! frystyk    32: #ifndef HT_MAX_SOCKETS
        !            33: #define HT_MAX_SOCKETS 6
        !            34: #endif
        !            35: 
        !            36: typedef struct _CBFInfo {
        !            37:     HTNetCallBack *    cbf;
        !            38:     int                status;      /* Status associated with this callback */
        !            39: } CBFInfo;
        !            40: 
        !            41: struct _HTStream {
        !            42:     CONST HTStreamClass *      isa;
        !            43:     /* ... */
        !            44: };
        !            45: 
        !            46: PRIVATE int    HTMaxActive = HT_MAX_SOCKETS;         /* Max active requests */
        !            47: PRIVATE HTList *HTNetActive = NULL;               /* List of active requests */
        !            48: PRIVATE HTList *HTNetPending = NULL;            /* List of pending requests */
        !            49: PRIVATE HTList *HTNetCBF = NULL;             /* List of call back functions */
2.1       frystyk    50: 
                     51: /* ------------------------------------------------------------------------- */
                     52: 
2.23    ! frystyk    53: /*
        !            54: **     Set the max number of simultanous sockets. Default is HT_MAX_SOCKETS
2.1       frystyk    55: */
2.23    ! frystyk    56: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
        !            57: {
        !            58:     if (newmax > 0) {
        !            59:        HTMaxActive = newmax;
        !            60:        return YES;
        !            61:     }
        !            62:     return NO;
        !            63: }
        !            64: 
        !            65: PUBLIC int HTNet_maxSocket (void)
2.1       frystyk    66: {
2.23    ! frystyk    67:     return HTMaxActive;
        !            68: }
        !            69: 
        !            70: /* ------------------------------------------------------------------------- */
        !            71: /*                       Termination Call Back Functions                    */
        !            72: /* ------------------------------------------------------------------------- */
        !            73: 
        !            74: /*     HTNet_Register
        !            75: **     --------------
        !            76: **     Register a call back function that is to be called on every
        !            77: **     termination of a request. Several call back functions can be registered
        !            78: **     in which case all of them are called in the order of which they
        !            79: **     were registered.
        !            80: **
        !            81: **     The status signifies which call back function to call depending of the 
        !            82: **     result of the request. This can be
        !            83: **
        !            84: **             HT_ERROR        An error occured
        !            85: **             HT_LOADED       The document was loaded
        !            86: **             HT_NO_DATA      OK, but no data
        !            87: **             HT_RETRY        Retry request after at a later time
        !            88: **             HT_ALL          All of above
        !            89: */
        !            90: PUBLIC BOOL HTNet_register (HTNetCallBack *cbf, int status)
        !            91: {
        !            92:     if (THD_TRACE) 
        !            93:        fprintf(TDEST, "Net register HTNetCallBack %p\n", (void *) cbf);
        !            94:     if (cbf) {
        !            95:        CBFInfo *cbfinfo = (CBFInfo *) calloc(1, sizeof(CBFInfo));
        !            96:        if (!cbfinfo) outofmem(__FILE__, "HTNet_register");
        !            97:        cbfinfo->cbf = cbf;
        !            98:        cbfinfo->status = status;
        !            99:        if (!HTNetCBF) HTNetCBF = HTList_new();
        !           100:        return HTList_addObject(HTNetCBF, (void *) cbfinfo);
        !           101:     }
        !           102:     return NO;
        !           103: }
        !           104: 
        !           105: /*     HTNet_unregister
        !           106: **     --------------
        !           107: **     Unregister a call back function that is to be called on every
        !           108: **     termination of a request.
        !           109: */
        !           110: PUBLIC BOOL HTNet_unregister (HTNetCallBack *cbf)
        !           111: {
        !           112:     if (THD_TRACE) 
        !           113:        fprintf(TDEST, "Net unreg.. HTNetCallBack %p\n", (void *) cbf);
        !           114:     if (HTNetCBF && cbf) {
        !           115:        HTList *cur = HTNetCBF;
        !           116:        CBFInfo *pres;
        !           117:        while ((pres = (CBFInfo *) HTList_nextObject(cur))) {
        !           118:            if (pres->cbf == cbf) {
        !           119:                HTList_removeObject(HTNetCBF, (void *) pres);
        !           120:                free(pres);
        !           121:                return YES;
        !           122:            }
        !           123:        }
        !           124:     }
        !           125:     return NO;
        !           126: }
2.1       frystyk   127: 
2.23    ! frystyk   128: /*     HTNet_unregisterAll
        !           129: **     -------------------
        !           130: **     Unregisters all call back functions
        !           131: */
        !           132: PUBLIC BOOL HTNet_unregisterAll (void)
        !           133: {
        !           134:     if (THD_TRACE) 
        !           135:        fprintf(TDEST, "Net unreg.. All callback functions\n");
        !           136:     if (HTNetCBF) {
        !           137:        HTList *cur = HTNetCBF;
        !           138:        CBFInfo *pres;
        !           139:        while ((pres = (CBFInfo *) HTList_nextObject(cur))) {
        !           140:            HTList_removeObject(HTNetCBF, (void *) pres);
        !           141:            free(pres);
        !           142:        }
        !           143:        HTList_delete(HTNetCBF);
        !           144:        HTNetCBF = NULL;
        !           145:        return YES;
        !           146:     }
        !           147:     return NO;
        !           148: }
        !           149: 
        !           150: /*     HTNet_callback
        !           151: **     --------------
        !           152: **     Call all the call back functions registered in the list IF not the 
        !           153: **     status is HT_IGNORE.
        !           154: **     The callback functions are called in the order of which they
        !           155: **     were registered. At the moment an application callback function is
        !           156: **     called, it can free the request object - it is no longer used by the
        !           157: **     Library.
        !           158: **     Returns YES if OK, else NO.
        !           159: */
        !           160: PUBLIC BOOL HTNet_callback (HTRequest * request, int status)
        !           161: {
        !           162:     if (HTNetCBF && request && status != HT_IGNORE) {  
        !           163:        int cnt = HTList_count(HTNetCBF);
        !           164:        while (--cnt >= 0) {
        !           165:            CBFInfo *pres = HTList_objectAt(HTNetCBF, cnt);
        !           166:            if (pres && (pres->status == status || pres->status == HT_ALL)) {
        !           167:                if (THD_TRACE)
        !           168:                    fprintf(TDEST, "Net callback %p (request=%p, status=%d)\n",
        !           169:                            (void *) pres->cbf, request, status);
        !           170:                (*(pres->cbf))(request, status);
        !           171:            }
        !           172:        }
        !           173:        return YES;
2.1       frystyk   174:     }
2.23    ! frystyk   175:     return NO;
2.1       frystyk   176: }
                    177: 
2.23    ! frystyk   178: /* ------------------------------------------------------------------------- */
        !           179: /*                             Request Queue                                */
        !           180: /* ------------------------------------------------------------------------- */
2.1       frystyk   181: 
2.23    ! frystyk   182: /*     HTNet_activeQueue
        !           183: **     -----------------
        !           184: **     Returns the list of active requests that are currently having an open
        !           185: **     connection.
        !           186: **     Returns list of HTNet objects or NULL if error
2.1       frystyk   187: */
2.23    ! frystyk   188: PUBLIC HTList *HTNet_activeQueue (void)
        !           189: {
        !           190:     return HTNetActive;
        !           191: }
2.17      frystyk   192: 
2.23    ! frystyk   193: /*     HTNet_pendingQueue
        !           194: **     ------------------
        !           195: **     Returns the list of pending requests that are waiting to become active
        !           196: **     Returns list of HTNet objects or NULL if error
        !           197: */
        !           198: PUBLIC HTList *HTNet_pendingQueue (void)
2.1       frystyk   199: {
2.23    ! frystyk   200:     return HTNetPending;
2.1       frystyk   201: }
                    202: 
2.23    ! frystyk   203: /* ------------------------------------------------------------------------- */
        !           204: /*                       Creation and deletion methods                      */
        !           205: /* ------------------------------------------------------------------------- */
        !           206: 
        !           207: /*                                                                HTNet_new
2.15      frystyk   208: **
2.23    ! frystyk   209: **     Create a new HTNet object as a new request to be handled. If we have
        !           210: **     more than HTMaxActive connections already then put this into the
        !           211: **     pending queue, else start the request by calling the call back
        !           212: **     function registered with this access method. 
        !           213: **     Returns YES if OK, else NO
        !           214: */
        !           215: PUBLIC BOOL HTNet_new (HTRequest * request, HTPriority priority)
        !           216: {
        !           217:     HTNet *me;
        !           218:     HTProtocol *prot;
        !           219:     if (!request) return HT_ERROR;
        !           220:     if (!HTNetActive) HTNetActive = HTList_new();
        !           221:     prot = HTAnchor_protocol(request->anchor);
        !           222: 
        !           223:     /* Create new net object and bind it to the request object */
        !           224:     if ((me = (HTNet *) calloc(1, sizeof(HTNet))) == NULL)
        !           225:        outofmem(__FILE__, "HTNet_new");
        !           226:     me->request = request;
        !           227:     request->net = me;
        !           228:     me->preemtive = (HTProtocol_preemtive(prot) || request->preemtive);
        !           229:     me->priority = priority;
        !           230:     me->sockfd = INVSOC;
        !           231:     if (!(me->cbf = HTProtocol_callback(prot))) {
        !           232:        if (THD_TRACE)
        !           233:            fprintf(TDEST, "HTNet_new... NO CALL BACK FUNCTION!\n");
        !           234:        free(me);
        !           235:        return NO;
        !           236:     }
        !           237: 
        !           238:     /*
        !           239:     ** Check if we can start the request, else put it into pending queue
        !           240:     ** If so then call the call back function associated with the anchor.
        !           241:     ** We use the INVSOC as we don't have a valid socket yet!
        !           242:     */
        !           243:     if (HTList_count(HTNetActive) < HTMaxActive) {
        !           244:        HTList_addObject(HTNetActive, (void *) me);
        !           245:        me->request->retrys++;
        !           246:        if (THD_TRACE)
        !           247:            fprintf(TDEST, "HTNet_new... starting request %p (retry=%d)\n",
        !           248:                    me->request, me->request->retrys);
        !           249:        (*(me->cbf))(INVSOC, me->request, FD_NONE);
        !           250:     } else {
        !           251:        if (!HTNetPending) HTNetPending = HTList_new();
        !           252:        if (THD_TRACE)
        !           253:            fprintf(TDEST, "HTNet_new... request %p registered as pending\n",
        !           254:                    me->request);
        !           255:        HTList_addObject(HTNetPending, (void *) me);
        !           256:     }
        !           257:     return YES;
        !           258: }
        !           259: 
        !           260: /*     delete_object
        !           261: **     -------------
        !           262: **     Deletes an HTNet object
2.15      frystyk   263: */
2.23    ! frystyk   264: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15      frystyk   265: {
2.23    ! frystyk   266:     if (THD_TRACE)
        !           267:        fprintf(TDEST, "HTNet_delete Remove net object %p\n", net);
        !           268:     if (net) {
        !           269:        int status = 0;
        !           270: 
        !           271:        /* Free stream with data FROM network to application */
        !           272:        if (net->target) {
        !           273:            if (status == HT_INTERRUPTED)
        !           274:                (*net->target->isa->abort)(net->target, NULL);
        !           275:            else
        !           276:                (*net->target->isa->_free)(net->target);
        !           277:        }
        !           278: 
        !           279:        /* Close socket */
        !           280:        if (net->sockfd != INVSOC) {
        !           281:            if ((status = NETCLOSE(net->sockfd)) < 0)
        !           282:                HTErrorSysAdd(net->request, ERR_FATAL,socerrno,NO,"NETCLOSE");
        !           283:            if (THD_TRACE)
        !           284:                fprintf(TDEST, "HTNet_delete closing socket %d\n",net->sockfd);
        !           285:            HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
        !           286:        }
        !           287:        if (net->isoc)
        !           288:            HTInputSocket_free(net->isoc);
        !           289:        if (net->request)
        !           290:            net->request->net = NULL;               /* Break link to request */
        !           291:        free(net);
        !           292:        return status ? NO : YES;
        !           293:     }
        !           294:     return NO;
        !           295: }
        !           296: 
        !           297: /*     HTNet_delete
        !           298: **     ------------
        !           299: **     Deletes the HTNet object from the list of active requests and calls
        !           300: **     any registered call back functions IF not the status is HT_IGNORE.
        !           301: **     This is used if we have internal requests that the app doesn't know
        !           302: **     about. We also see if we have pending requests that can be started
        !           303: **     up now when we have a socket free.
        !           304: **     The callback functions are called in the reverse order of which they
        !           305: **     were registered (last one first)
        !           306: */
        !           307: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
        !           308: {
        !           309:     if (THD_TRACE) 
        !           310:        fprintf(TDEST,"HTNetDelete. Net Object and call callback functions\n");
        !           311:     if (HTNetActive && net) {
        !           312: 
        !           313:        /* Remove object and call callback functions */
        !           314:        HTRequest *request = net->request;
        !           315:        HTList_removeObject(HTNetActive, (void *) net);
        !           316:        delete_object(net, status);
        !           317:        HTNet_callback(request, status);
        !           318: 
        !           319:        /* See if we can start a pending request */
        !           320:        if (HTList_count(HTNetActive) < HTMaxActive &&
        !           321:            HTList_count(HTNetPending)) {
        !           322:            HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
        !           323:            if (next) {
        !           324:                HTList_addObject(HTNetActive, (void *) next);
        !           325:                next->request->retrys++;
        !           326:                if (THD_TRACE)
        !           327:                    fprintf(TDEST,"HTNet_delete start request %p from queue\n",
        !           328:                            next->request);
        !           329:                (*(next->cbf))(INVSOC, next->request, FD_NONE);
        !           330:            }
        !           331:        }
        !           332:        return YES;
        !           333:     }
        !           334:     return NO;
        !           335: }
        !           336: 
        !           337: /*     HTNet_deleteAll
        !           338: **     ---------------
        !           339: **     Deletes all HTNet object that might either be active or pending
        !           340: **     We DO NOT call the call back functions and we don't care about open
        !           341: **     socket descriptors. A crude way of saying goodbye!
        !           342: */
        !           343: PUBLIC BOOL HTNet_deleteAll (void)
        !           344: {
        !           345:     if (THD_TRACE) 
        !           346:        fprintf(TDEST, "HTNetDelete. Removing ALL Net - NO call backs\n"); 
        !           347:     if (HTNetPending) {
        !           348:        HTList *cur = HTNetPending;
        !           349:        HTNet *pres;
        !           350:        while ((pres = (HTNet *) HTList_nextObject(cur)))
        !           351:            delete_object(pres, HT_INTERRUPTED);
        !           352:        HTList_delete(HTNetPending);
        !           353:        HTNetPending = NULL;
        !           354:     }
        !           355:     if (HTNetActive) {
        !           356:        HTList *cur = HTNetActive;
        !           357:        HTNet *pres;
        !           358:        while ((pres = (HTNet *) HTList_nextObject(cur)))
        !           359:            delete_object(pres, HT_INTERRUPTED);
        !           360:        HTList_delete(HTNetActive);
        !           361:        HTNetActive = NULL;
        !           362:     }
        !           363:     return NO;
2.15      frystyk   364: }
                    365: 
2.23    ! frystyk   366: /* ------------------------------------------------------------------------- */
        !           367: /*                             Killing requests                             */
        !           368: /* ------------------------------------------------------------------------- */
        !           369: 
        !           370: /*     HTNet_kill
        !           371: **     ----------
        !           372: **     Kill the request by calling the call back function with a request for 
        !           373: **     closing the connection. Does not remove the object. This is done by
        !           374: **     HTNet_delete() function which is called by the load routine.
        !           375: **     Returns OK if success, NO on error
        !           376: */
        !           377: PUBLIC BOOL HTNet_kill (HTNet * me)
        !           378: {
        !           379:     if (HTNetActive && me) {
        !           380:        HTNet *pres;
        !           381:        while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL) {
        !           382:            if (pres == me) {
        !           383:                (*(pres->cbf))(INVSOC, pres->request, FD_CLOSE);
        !           384:                return YES;
        !           385:            }
        !           386:        }
        !           387:     }
        !           388:     if (THD_TRACE)
        !           389:        fprintf(TDEST, "HTNet_kill.. Request %p is not registered\n", me);
        !           390:     return NO;
        !           391: }
        !           392: 
        !           393: /*     HTNet_killAll
        !           394: **     -------------
        !           395: **     Kills all registered (active+pending) requests by calling the call
        !           396: **     back function with a request for closing the connection. We do not
        !           397: **     remove the HTNet object as it is done by HTNet_delete().
        !           398: **     Returns OK if success, NO on error
        !           399: */
        !           400: PUBLIC BOOL HTNet_killAll (void)
        !           401: {
        !           402:     HTNet *pres;
        !           403:     if (THD_TRACE)
        !           404:        fprintf(TDEST, "HTNet_kill.. ALL registered requests!!!\n");
        !           405: 
        !           406:     /* We start off in pending queue so we avoid racing */
        !           407:     if (HTNetPending) {
        !           408:        while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
        !           409:            (*(pres->cbf))(INVSOC, pres->request, FD_CLOSE);
        !           410:            HTList_removeObject(HTNetPending, pres);
        !           411:        }
        !           412:     }
        !           413:     if (HTNetActive) {
        !           414:        while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
        !           415:            (*(pres->cbf))(INVSOC, pres->request, FD_CLOSE);
        !           416:     }
        !           417:     return YES;
        !           418: }
2.17      frystyk   419: 
2.23    ! frystyk   420: #if 0
2.20      frystyk   421: /*
                    422: **  LibraryCallback - "glue" between 3.0 thread code and new callback functions
                    423: **  map return codes into a simple yes/no model. 
                    424: */
2.21      frystyk   425: PRIVATE int LibraryCallback ARGS3(SOCKET, s, HTRequest *, rq, SockOps, f)
2.20      frystyk   426: {
                    427:     int status = 0 ;
                    428:     HTEventState state ;
                    429:     HTProtocol * proto = (HTProtocol *)
                    430:             HTAnchor_protocol( rq -> anchor) ;
                    431: 
                    432:     /* begin */    
                    433: 
                    434:     if (proto == 0)    /* Whoa! No protocol! */
                    435:        return -1;
2.23    ! frystyk   436:     status = proto->callback( s, rq, f) ;
2.20      frystyk   437:     if (status != HT_WOULD_BLOCK) {   /* completed - good or bad... */
                    438:         if (THD_TRACE) 
                    439:             fprintf(TDEST, "LibCallBack. Calling Terminate...\n");
                    440:        if (status != HT_OK) {
                    441:            HTLoadTerminate(rq, status);
                    442:            state = HTEventRequestTerminate( rq, status) ;
                    443:            /* if the state isn't EVENT_QUIT */
                    444:            if (! HTEventCheckState( rq, state ))
                    445:                return HT_OK;  /* treat as failure */
                    446:        }
                    447:     }  /* if status */
                    448:     return HT_WOULD_BLOCK;
                    449: }
2.17      frystyk   450: 
2.23    ! frystyk   451: /*                                                               HTNetState
2.1       frystyk   452: **
                    453: **     This function registers a socket as waiting for the action given
                    454: **     (read or write etc.).
2.17      frystyk   455: **
                    456: **     Charlie Brooks - we handle the interrupt thread state internally to this module 
                    457: **      setting the interrupt on a socket disables it from read/write.
2.1       frystyk   458: */
2.23    ! frystyk   459: PUBLIC void HTNetState ARGS2(SOCKFD, sockfd, HTNetAction, action)
2.1       frystyk   460: {
2.23    ! frystyk   461:     register HTNet * pres ;
        !           462:     HTList * cur = HTNetActive ;
2.17      frystyk   463:     int found = 0 ;
                    464:     HTRequest * reqst ;
                    465: 
2.9       frystyk   466: #ifdef _WIN32
2.23    ! frystyk   467:     if (sockfd <= 2) 
        !           468:        sockfd = _get_osfhandle(sockfd);
2.9       frystyk   469: #endif
                    470:   
2.1       frystyk   471:     if (THD_TRACE) {
                    472:        static char *actionmsg[] = {
                    473:            "SET WRITE",
                    474:            "CLEAR WRITE",
                    475:            "SET READ",
                    476:            "CLEAR READ",
2.4       frystyk   477:            "SET INTERRUPT",
                    478:            "CLEAR INTERRUPT",
2.17      frystyk   479:            "CLOSE",
                    480:            "SET CONNECT",
                    481:            "CLEAR CONNECT"
2.1       frystyk   482:            };
2.7       frystyk   483:        fprintf(TDEST,
2.23    ! frystyk   484:                "Net......... Registering socket number %d for action %s\n",
2.1       frystyk   485:                sockfd, *(actionmsg+action));
2.17      frystyk   486:     }   /* if */
                    487: 
                    488:     FD_SET( sockfd, &HTfd_libs) ;
                    489:     if (libMaxSock < sockfd)
                    490:        libMaxSock = sockfd ;
                    491: 
                    492: 
2.23    ! frystyk   493:     while ((pres = (HTNet *)HTList_nextObject(cur) ) != 0) { 
2.17      frystyk   494:         if (pres->sockfd == sockfd) {
                    495:             found = 1 ;
                    496:             break ;
                    497:         }   /* if */
                    498:     }       /* while */
                    499: 
                    500:     if (! found)    /* how'd you get here? */
                    501:         return ;
                    502: 
                    503:     reqst = pres->request ;
2.1       frystyk   504:     switch (action) {
                    505:       case THD_SET_WRITE:
2.17      frystyk   506:       case THD_SET_CONNECT: 
                    507:         HTEvent_Register( sockfd, reqst, action == THD_SET_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT , 
                    508:                LibraryCallback, 0);
2.1       frystyk   509:        break;
                    510: 
                    511:       case THD_CLR_WRITE:
2.17      frystyk   512:       case THD_CLR_CONNECT: 
                    513:         HTEvent_UnRegister( sockfd, action == THD_CLR_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT) ;
2.1       frystyk   514:        break;
                    515: 
                    516:       case THD_SET_READ:
2.17      frystyk   517:         HTEvent_Register( sockfd, reqst, (SockOps)FD_READ, LibraryCallback, 0);  
2.1       frystyk   518:        break;
                    519: 
                    520:       case THD_CLR_READ:
2.17      frystyk   521:         HTEvent_UnRegister( sockfd, FD_WRITE) ;
2.1       frystyk   522:        break;
                    523: 
                    524:       case THD_CLOSE:
2.17      frystyk   525:         HTEvent_UnRegister( sockfd, FD_ALL) ;
                    526:        FD_CLR( sockfd, &HTfd_libs);
                    527:        FD_CLR( sockfd, &HTfd_intr);
                    528:        libMaxSock = 0 ;
2.23    ! frystyk   529:        while ((pres = (HTNet *)HTList_nextObject(cur) ) != 0) { 
2.17      frystyk   530:            if (pres->sockfd > libMaxSock) {
                    531:                libMaxSock = sockfd ;
                    532:            }   /* if */
                    533:        }       /* while */
                    534: 
2.1       frystyk   535:        break;
                    536: 
2.17      frystyk   537: /*
                    538:  * we handle interrupts locally ... only library sockets can 
                    539:  * be interrupted? 
                    540:  */
                    541: 
2.2       frystyk   542:       case THD_SET_INTR:
2.17      frystyk   543:         HTEvent_UnRegister( sockfd, (SockOps)(FD_READ | FD_WRITE) );
                    544:         FD_SET( sockfd, &HTfd_intr) ;
2.1       frystyk   545:        break;
                    546: 
2.2       frystyk   547:       case THD_CLR_INTR:
2.17      frystyk   548:         FD_CLR( sockfd, &HTfd_intr) ;
                    549:        HTEvent_UnRegister(sockfd, FD_ALL) ;  /* no sin to unregister and unregistered socket */
2.2       frystyk   550:        break;
                    551: 
2.1       frystyk   552:       default:
                    553:        if (THD_TRACE)
2.23    ! frystyk   554:            fprintf(TDEST, "Net...... Illegal socket action (%d)\n", (int)action);
2.1       frystyk   555:     }
2.17      frystyk   556:     return ;
2.1       frystyk   557: }
2.23    ! frystyk   558: #endif
2.1       frystyk   559: 
                    560: 

Webmaster