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

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

Webmaster