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

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.25      frystyk    23: #include "HTAlert.h"
2.23      frystyk    24: #include "HTReqMan.h"
2.17      frystyk    25: #include "HTEvntrg.h"
2.23      frystyk    26: #include "HTStream.h"
2.24      frystyk    27: #include "HTNetMan.h"                                   /* Implemented here */
2.1       frystyk    28: 
2.9       frystyk    29: #ifdef WIN32
                     30: #include <io.h>
                     31: #endif
                     32: 
2.23      frystyk    33: #ifndef HT_MAX_SOCKETS
                     34: #define HT_MAX_SOCKETS 6
                     35: #endif
                     36: 
2.33      frystyk    37: typedef struct _NetCall {
2.30      frystyk    38:     HTNetCallback *    cbf;
2.23      frystyk    39:     int                status;      /* Status associated with this callback */
2.33      frystyk    40: } NetCall;
2.23      frystyk    41: 
                     42: struct _HTStream {
                     43:     CONST HTStreamClass *      isa;
                     44:     /* ... */
                     45: };
                     46: 
                     47: PRIVATE int    HTMaxActive = HT_MAX_SOCKETS;         /* Max active requests */
2.33      frystyk    48: PRIVATE HTList *HTBefore = NULL;             /* List of call back functions */
                     49: PRIVATE HTList *HTAfter = NULL;                      /* List of call back functions */
2.24      frystyk    50: 
2.23      frystyk    51: PRIVATE HTList *HTNetActive = NULL;               /* List of active requests */
                     52: PRIVATE HTList *HTNetPending = NULL;            /* List of pending requests */
2.24      frystyk    53: PRIVATE HTList *HTNetPersistent = NULL;           /* List of persistent connections */
2.1       frystyk    54: 
                     55: /* ------------------------------------------------------------------------- */
                     56: 
2.23      frystyk    57: /*
                     58: **     Set the max number of simultanous sockets. Default is HT_MAX_SOCKETS
2.1       frystyk    59: */
2.23      frystyk    60: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
                     61: {
                     62:     if (newmax > 0) {
                     63:        HTMaxActive = newmax;
                     64:        return YES;
                     65:     }
                     66:     return NO;
                     67: }
                     68: 
                     69: PUBLIC int HTNet_maxSocket (void)
2.1       frystyk    70: {
2.23      frystyk    71:     return HTMaxActive;
                     72: }
                     73: 
                     74: /* ------------------------------------------------------------------------- */
2.33      frystyk    75: /*                             Call Back Functions                          */
2.23      frystyk    76: /* ------------------------------------------------------------------------- */
                     77: 
2.33      frystyk    78: /*     HTNetCall_add
                     79: **     -------------
                     80: **     Register a call back function that is to be called on every request.
                     81: **     Several call back functions can be registered
2.23      frystyk    82: **     in which case all of them are called in the order of which they
                     83: **     were registered.
                     84: **
                     85: **     The status signifies which call back function to call depending of the 
                     86: **     result of the request. This can be
                     87: **
                     88: **             HT_ERROR        An error occured
                     89: **             HT_LOADED       The document was loaded
                     90: **             HT_NO_DATA      OK, but no data
2.33      frystyk    91: **             HT_REDIRECT     If we received a redirection
2.23      frystyk    92: **             HT_RETRY        Retry request after at a later time
                     93: **             HT_ALL          All of above
                     94: */
2.33      frystyk    95: PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback *cbf, int status)
2.23      frystyk    96: {
2.33      frystyk    97:     if (WWWTRACE) 
                     98:        TTYPrint(TDEST, "Call Add.... HTNetCallback %p\n", (void *) cbf);
                     99:     if (list && cbf) {
                    100:        NetCall *me = (NetCall *) calloc(1, sizeof(NetCall));
                    101:        if (!me) outofmem(__FILE__, "HTNet_register");
                    102:        me->cbf = cbf;
                    103:        me->status = status;
                    104:        return HTList_addObject(list, (void *) me);
2.23      frystyk   105:     }
                    106:     return NO;
                    107: }
                    108: 
2.33      frystyk   109: /*     HTNetCall_delete
                    110: **     ----------------
                    111: **     Unregister a call back function from a list
2.23      frystyk   112: */
2.33      frystyk   113: PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
2.23      frystyk   114: {
2.33      frystyk   115:     if (WWWTRACE) 
                    116:        TTYPrint(TDEST, "Call delete HTNetCallback %p\n", (void *) cbf);
                    117:     if (list && cbf) {
                    118:        HTList *cur = list;
                    119:        NetCall *pres;
                    120:        while ((pres = (NetCall *) HTList_nextObject(cur))) {
2.23      frystyk   121:            if (pres->cbf == cbf) {
2.33      frystyk   122:                HTList_removeObject(list, (void *) pres);
2.23      frystyk   123:                free(pres);
                    124:                return YES;
                    125:            }
                    126:        }
                    127:     }
                    128:     return NO;
                    129: }
2.1       frystyk   130: 
2.33      frystyk   131: /*     HTNetCall_deleteAll
2.23      frystyk   132: **     -------------------
                    133: **     Unregisters all call back functions
                    134: */
2.33      frystyk   135: PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
2.23      frystyk   136: {
2.33      frystyk   137:     if (WWWTRACE) 
                    138:        TTYPrint(TDEST, "Call delete All callback functions\n");
                    139:     if (list) {
                    140:        HTList *cur = list;
                    141:        NetCall *pres;
                    142:        while ((pres = (NetCall *) HTList_nextObject(cur))) {
                    143:            HTList_removeObject(list, (void *) pres);
2.23      frystyk   144:            free(pres);
                    145:        }
2.33      frystyk   146:        HTList_delete(list);
2.23      frystyk   147:        return YES;
                    148:     }
                    149:     return NO;
                    150: }
                    151: 
2.33      frystyk   152: /*     HTNetCall_execute
                    153: **     -----------------
2.23      frystyk   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.
2.33      frystyk   160: **     Returns what the last callback function returns
2.23      frystyk   161: */
2.33      frystyk   162: PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
2.23      frystyk   163: {
2.33      frystyk   164:     int ret = HT_OK;
                    165:     if (list && request && status != HT_IGNORE) {      
                    166:        int cnt = HTList_count(list);
2.23      frystyk   167:        while (--cnt >= 0) {
2.33      frystyk   168:            NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
2.23      frystyk   169:            if (pres && (pres->status == status || pres->status == HT_ALL)) {
2.33      frystyk   170:                if (WWWTRACE)
                    171:                    TTYPrint(TDEST,"Net callback %p (request=%p, status=%d)\n",
2.23      frystyk   172:                            (void *) pres->cbf, request, status);
2.33      frystyk   173:                if ((ret = (*(pres->cbf))(request, status)) != HT_OK) break;
2.23      frystyk   174:            }
                    175:        }
2.1       frystyk   176:     }
2.33      frystyk   177:     return ret;
                    178: }
                    179: 
                    180: /*
                    181: **     Global set of callback functions BEFORE the request is issued
                    182: **     list can be NULL
                    183: */
                    184: PUBLIC BOOL HTNet_setBefore (HTList *list)
                    185: {
                    186:     if (HTBefore) HTNetCall_deleteAll(HTBefore);
                    187:     HTBefore = list;
                    188:     return YES;
                    189: }
                    190: 
                    191: PUBLIC HTList * HTNet_before (void)
                    192: {
                    193:     return HTBefore;
                    194: }
                    195: 
                    196: PUBLIC int HTNet_callBefore (HTRequest *request, int status)
                    197: {
                    198:     return HTNetCall_execute(HTBefore, request, status);
                    199: }
                    200: 
                    201: PUBLIC BOOL HTNetCall_addBefore (HTNetCallback *cbf, int status)
                    202: {
                    203:     if (!HTBefore) HTBefore = HTList_new();
                    204:     return HTNetCall_add(HTBefore, cbf, status);
                    205: }
                    206: 
                    207: /*
                    208: **     Global set of callback functions AFTER the request is issued
                    209: **     list can be NULL
                    210: */
                    211: PUBLIC BOOL HTNet_setAfter (HTList *list)
                    212: {
                    213:     if (HTAfter) HTNetCall_deleteAll(HTAfter);
                    214:     HTAfter = list;
                    215:     return YES;
                    216: }
                    217: 
                    218: PUBLIC HTList * HTNet_after (void)
                    219: {
                    220:     return HTAfter;
                    221: }
                    222: 
                    223: PUBLIC int HTNet_callAfter (HTRequest *request, int status)
                    224: {
                    225:     return HTNetCall_execute(HTAfter, request, status);
                    226: }
                    227: 
                    228: PUBLIC BOOL HTNetCall_addAfter (HTNetCallback *cbf, int status)
                    229: {
                    230:     if (!HTAfter) HTAfter = HTList_new();
                    231:     return HTNetCall_add(HTAfter, cbf, status);
2.1       frystyk   232: }
                    233: 
2.23      frystyk   234: /* ------------------------------------------------------------------------- */
                    235: /*                             Request Queue                                */
                    236: /* ------------------------------------------------------------------------- */
2.1       frystyk   237: 
2.23      frystyk   238: /*     HTNet_activeQueue
                    239: **     -----------------
                    240: **     Returns the list of active requests that are currently having an open
                    241: **     connection.
                    242: **     Returns list of HTNet objects or NULL if error
2.1       frystyk   243: */
2.23      frystyk   244: PUBLIC HTList *HTNet_activeQueue (void)
                    245: {
                    246:     return HTNetActive;
                    247: }
2.17      frystyk   248: 
2.28      frystyk   249: /*     HTNet_activeCount
                    250: **     ----------------
                    251: **     Returns the number of active requests
                    252: */
2.29      frystyk   253: PUBLIC BOOL HTNet_idle (void)
2.28      frystyk   254: {
2.29      frystyk   255:     return HTList_isEmpty(HTNetActive);
2.28      frystyk   256: }
                    257: 
2.23      frystyk   258: /*     HTNet_pendingQueue
                    259: **     ------------------
                    260: **     Returns the list of pending requests that are waiting to become active
                    261: **     Returns list of HTNet objects or NULL if error
                    262: */
                    263: PUBLIC HTList *HTNet_pendingQueue (void)
2.1       frystyk   264: {
2.23      frystyk   265:     return HTNetPending;
2.1       frystyk   266: }
                    267: 
2.23      frystyk   268: /* ------------------------------------------------------------------------- */
                    269: /*                       Creation and deletion methods                      */
                    270: /* ------------------------------------------------------------------------- */
                    271: 
2.27      frystyk   272: /*     HTNet_duplicate
                    273: **     ---------------
                    274: **     Creates a new HTNet object as a duplicate of the same request.
                    275: **     Returns YES if OK, else NO
                    276: **     BUG: We do not check if we have a socket free!
                    277: */
                    278: PUBLIC BOOL HTNet_dup (HTNet *src, HTNet **dest)
                    279: {
                    280:     *dest = NULL;
                    281:     if (!src) return NO;
                    282:     if ((*dest = (HTNet *) calloc(1, sizeof(HTNet))) == NULL)
                    283:        outofmem(__FILE__, "HTNet_dup");
                    284:     memcpy(*dest, src, sizeof(HTNet));
                    285:     return YES;
                    286: }
                    287: 
2.30      frystyk   288: /*     HTNet_priority
                    289: **     --------------
                    290: **     Get the current priority of the Net object
                    291: */
                    292: PUBLIC HTPriority HTNet_priority (HTNet * net)
                    293: {
                    294:     return (net ? net->priority : -1);
                    295: }
                    296: 
                    297: /*     HTNet_setPriority
                    298: **     -----------------
                    299: **     Set the current priority of the Net object
                    300: **     This will change the priority next time the thread is blocked
                    301: */
                    302: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
                    303: {
                    304:     if (net) {
                    305:        net->priority = priority;
                    306:        return YES;
                    307:     }
                    308:     return NO;
                    309: }
                    310: 
2.36    ! frystyk   311: /*     create_object
        !           312: **     -------------
        !           313: **     Creates an HTNet object
        !           314: */
        !           315: PRIVATE HTNet * create_object (HTRequest * request)
        !           316: {
        !           317:     HTNet * me;
        !           318:     if ((me = (HTNet *) calloc(1, sizeof(HTNet))) == NULL)
        !           319:        outofmem(__FILE__, "HTNet_new");
        !           320:     me->request = request;
        !           321:     request->net = me;
        !           322:     return me;
        !           323: }
        !           324: 
        !           325: 
2.30      frystyk   326: /*     HTNet_new
                    327: **     ---------
2.23      frystyk   328: **     Create a new HTNet object as a new request to be handled. If we have
                    329: **     more than HTMaxActive connections already then put this into the
                    330: **     pending queue, else start the request by calling the call back
                    331: **     function registered with this access method. 
                    332: **     Returns YES if OK, else NO
                    333: */
2.30      frystyk   334: PUBLIC BOOL HTNet_new (HTRequest * request)
2.23      frystyk   335: {
2.33      frystyk   336:     int status;
                    337:     HTNet * me;
2.23      frystyk   338:     HTProtocol *prot;
2.33      frystyk   339:     char * physical;
2.27      frystyk   340:     if (!request) return NO;
2.33      frystyk   341:     /*
                    342:     ** First we do all the "BEFORE" callbacks in order to see if we are to
                    343:     ** continue with this request or not. If we receive a callback status
                    344:     ** that is NOT HT_OK then jump directly to the after callbacks and return
                    345:     */
2.34      frystyk   346:     if ((status = HTNetCall_execute(HTBefore, request, HT_OK)) != HT_OK) {
2.33      frystyk   347:        HTNetCall_execute(HTAfter, request, status);
                    348:        return YES;
                    349:     }
                    350: 
2.36    ! frystyk   351:     /*
        !           352:     ** If no translation was provided by the application then use the anchor
        !           353:     ** address directly
        !           354:     */
2.33      frystyk   355:     if (!(physical = HTAnchor_physical(request->anchor)) || !*physical) {
2.36    ! frystyk   356:        char * addr = HTAnchor_address((HTAnchor *) request->anchor);
        !           357:        if (WWWTRACE) TTYPrint(TDEST, "HTNet New... USING DEFAULT ADDRESS!\n");
        !           358:        HTAnchor_setPhysical(request->anchor, addr);
        !           359:        HTProtocol_find(request, request->anchor);
        !           360:        FREE(addr);
2.33      frystyk   361:     }
                    362: 
2.23      frystyk   363:     if (!HTNetActive) HTNetActive = HTList_new();
2.26      frystyk   364:     prot = (HTProtocol *) HTAnchor_protocol(request->anchor);
2.23      frystyk   365: 
                    366:     /* Create new net object and bind it to the request object */
2.36    ! frystyk   367:     if ((me = create_object(request)) == NULL) return NO;
2.23      frystyk   368:     me->preemtive = (HTProtocol_preemtive(prot) || request->preemtive);
2.30      frystyk   369:     me->priority = request->priority;
2.23      frystyk   370:     me->sockfd = INVSOC;
                    371:     if (!(me->cbf = HTProtocol_callback(prot))) {
2.36    ! frystyk   372:        if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... NO CALL BACK FUNCTION!\n");
2.23      frystyk   373:        free(me);
                    374:        return NO;
                    375:     }
2.25      frystyk   376:     request->retrys++;
2.23      frystyk   377: 
                    378:     /*
                    379:     ** Check if we can start the request, else put it into pending queue
                    380:     ** If so then call the call back function associated with the anchor.
                    381:     ** We use the INVSOC as we don't have a valid socket yet!
                    382:     */
                    383:     if (HTList_count(HTNetActive) < HTMaxActive) {
                    384:        HTList_addObject(HTNetActive, (void *) me);
2.33      frystyk   385:        if (WWWTRACE)
2.31      frystyk   386:            TTYPrint(TDEST, "HTNet_new... starting request %p (retry=%d)\n",
2.25      frystyk   387:                    request, request->retrys);
                    388:        (*(me->cbf))(me->sockfd, request, FD_NONE);
2.23      frystyk   389:     } else {
2.35      frystyk   390:        HTAlertCallback *cbf = HTAlert_find(HT_PROG_WAIT);
2.23      frystyk   391:        if (!HTNetPending) HTNetPending = HTList_new();
2.33      frystyk   392:        if (WWWTRACE)
2.31      frystyk   393:            TTYPrint(TDEST, "HTNet_new... request %p registered as pending\n",
2.25      frystyk   394:                    request);
2.35      frystyk   395:        if (cbf) (*cbf)(request, HT_PROG_WAIT, HT_MSG_NULL, NULL, NULL, NULL);
2.25      frystyk   396:        HTList_addObject(HTNetPending, (void *) me);    
2.23      frystyk   397:     }
                    398:     return YES;
                    399: }
                    400: 
2.36    ! frystyk   401: /*     HTNet_create
        !           402: **     ------------
        !           403: **     This function creates a new HTNet object and assigns the socket number
        !           404: **     to it. This is intended to be used when you are going to listen on a 
        !           405: **     socket using the HTDoListen() function in HTTCP.c. The function do NOT
        !           406: **     call any of the callback functions.
        !           407: **     Returns YES if OK, else NO
        !           408: */
        !           409: PUBLIC BOOL HTNet_create (HTRequest * request, SOCKET sockfd)
        !           410: {
        !           411:     HTNet * me;
        !           412:     if (WWWTRACE) TTYPrint(TDEST, "HTNet_create empty Net object\n");
        !           413:     if (!request || sockfd==INVSOC) return NO;
        !           414:     if ((me = create_object(request)) == NULL) return NO;
        !           415:     me->preemtive = request->preemtive;
        !           416:     me->priority = request->priority;
        !           417:     me->sockfd = sockfd;
        !           418:     return YES;
        !           419: }
        !           420: 
2.23      frystyk   421: /*     delete_object
                    422: **     -------------
                    423: **     Deletes an HTNet object
2.15      frystyk   424: */
2.23      frystyk   425: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15      frystyk   426: {
2.33      frystyk   427:     if (WWWTRACE)
2.31      frystyk   428:        TTYPrint(TDEST, "HTNet_delete Remove net object %p\n", net);
2.23      frystyk   429:     if (net) {
                    430:        int status = 0;
                    431: 
                    432:        /* Free stream with data FROM network to application */
                    433:        if (net->target) {
                    434:            if (status == HT_INTERRUPTED)
                    435:                (*net->target->isa->abort)(net->target, NULL);
                    436:            else
                    437:                (*net->target->isa->_free)(net->target);
                    438:        }
                    439: 
                    440:        /* Close socket */
                    441:        if (net->sockfd != INVSOC) {
2.24      frystyk   442:            if (HTDNS_socket(net->dns) == INVSOC) {
                    443:                if ((status = NETCLOSE(net->sockfd)) < 0)
2.33      frystyk   444:                    HTRequest_addSystemError(net->request, ERR_FATAL,
                    445:                                             socerrno, NO, "NETCLOSE");
                    446:                if (WWWTRACE)
2.31      frystyk   447:                    TTYPrint(TDEST, "HTNet_delete closing %d\n", net->sockfd);
2.25      frystyk   448:                HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
2.24      frystyk   449:            } else {
2.33      frystyk   450:                if (WWWTRACE)
2.31      frystyk   451:                    TTYPrint(TDEST, "HTNet_delete keeping %d\n", net->sockfd);
2.25      frystyk   452:                HTDNS_clearActive(net->dns);
                    453:                /* Here we should probably use a low priority */
2.27      frystyk   454:                HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
2.25      frystyk   455:                HTEvent_Register(net->sockfd, net->request, (SockOps) FD_READ,
                    456:                                 HTDNS_closeSocket, net->priority);
2.24      frystyk   457:            }
2.23      frystyk   458:        }
                    459:        if (net->isoc)
                    460:            HTInputSocket_free(net->isoc);
                    461:        if (net->request)
                    462:            net->request->net = NULL;               /* Break link to request */
                    463:        free(net);
                    464:        return status ? NO : YES;
                    465:     }
                    466:     return NO;
                    467: }
                    468: 
                    469: /*     HTNet_delete
                    470: **     ------------
                    471: **     Deletes the HTNet object from the list of active requests and calls
                    472: **     any registered call back functions IF not the status is HT_IGNORE.
                    473: **     This is used if we have internal requests that the app doesn't know
                    474: **     about. We also see if we have pending requests that can be started
                    475: **     up now when we have a socket free.
                    476: **     The callback functions are called in the reverse order of which they
                    477: **     were registered (last one first)
                    478: */
                    479: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
                    480: {
2.33      frystyk   481:     if (WWWTRACE) 
                    482:        TTYPrint(TDEST,"HTNetDelete. Object and call callback functions\n");
2.23      frystyk   483:     if (HTNetActive && net) {
2.36    ! frystyk   484:        SOCKET cs = net->sockfd;                           /* Current sockfd */
2.23      frystyk   485: 
                    486:        /* Remove object and call callback functions */
                    487:        HTRequest *request = net->request;
                    488:        HTList_removeObject(HTNetActive, (void *) net);
                    489:        delete_object(net, status);
2.33      frystyk   490:        HTNetCall_execute(HTAfter, request, status);
2.23      frystyk   491: 
2.25      frystyk   492:        /*
                    493:        ** See first if we have a persistent request queued up for this socket
                    494:        ** If not then see if there is a pending request
                    495:        */
                    496:        if (HTNetPersistent) {
                    497:            HTList *cur = HTNetPersistent;
                    498:            HTNet *next;
                    499:            while ((next = (HTNet *) HTList_nextObject(cur))) {
                    500:                if (next->sockfd == cs) {
2.33      frystyk   501:                    if (WWWTRACE)
2.31      frystyk   502:                        TTYPrint(TDEST, "HTNet delete launch WARM request %p\n",
2.25      frystyk   503:                                next->request);
2.28      frystyk   504:                    HTList_addObject(HTNetActive, (void *) next);
                    505:                    HTList_removeObject(HTNetPersistent, (void *) next);
2.25      frystyk   506:                    (*(next->cbf))(next->sockfd, next->request, FD_NONE);
                    507:                    break;
                    508:                }
                    509:            }
                    510:        } else if (HTList_count(HTNetActive) < HTMaxActive &&
                    511:                   HTList_count(HTNetPending)) {
2.23      frystyk   512:            HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
                    513:            if (next) {
                    514:                HTList_addObject(HTNetActive, (void *) next);
2.33      frystyk   515:                if (WWWTRACE)
2.31      frystyk   516:                    TTYPrint(TDEST,"HTNet delete launch PENDING request %p\n",
2.23      frystyk   517:                            next->request);
                    518:                (*(next->cbf))(INVSOC, next->request, FD_NONE);
                    519:            }
                    520:        }
                    521:        return YES;
                    522:     }
                    523:     return NO;
                    524: }
                    525: 
                    526: /*     HTNet_deleteAll
                    527: **     ---------------
                    528: **     Deletes all HTNet object that might either be active or pending
2.25      frystyk   529: **     We DO NOT call the call back functions - A crude way of saying goodbye!
2.23      frystyk   530: */
                    531: PUBLIC BOOL HTNet_deleteAll (void)
                    532: {
2.33      frystyk   533:     if (WWWTRACE) 
2.31      frystyk   534:        TTYPrint(TDEST, "HTNetDelete. Remove all Net objects, NO callback\n"); 
2.25      frystyk   535:     if (HTNetPersistent) {
                    536:        HTList *cur = HTNetPersistent;
                    537:        HTNet *pres;
                    538:        while ((pres = (HTNet *) HTList_nextObject(cur))) {
                    539:            pres->sockfd = INVSOC;          /* Don't close it more than once */
                    540:            delete_object(pres, HT_INTERRUPTED);
                    541:        }
                    542:        HTList_delete(HTNetPersistent);
                    543:        HTNetPersistent = NULL;
                    544:     }
2.23      frystyk   545:     if (HTNetPending) {
                    546:        HTList *cur = HTNetPending;
                    547:        HTNet *pres;
                    548:        while ((pres = (HTNet *) HTList_nextObject(cur)))
                    549:            delete_object(pres, HT_INTERRUPTED);
                    550:        HTList_delete(HTNetPending);
                    551:        HTNetPending = NULL;
                    552:     }
                    553:     if (HTNetActive) {
                    554:        HTList *cur = HTNetActive;
                    555:        HTNet *pres;
                    556:        while ((pres = (HTNet *) HTList_nextObject(cur)))
                    557:            delete_object(pres, HT_INTERRUPTED);
                    558:        HTList_delete(HTNetActive);
                    559:        HTNetActive = NULL;
                    560:     }
                    561:     return NO;
2.15      frystyk   562: }
                    563: 
2.25      frystyk   564: /*     HTNet_wait
                    565: **     ----------
                    566: **     Let a net object wait for a persistent socket. It will be launched
                    567: **     from the HTNet_delete() function
                    568: */
                    569: PUBLIC BOOL HTNet_wait (HTNet *net)
                    570: {
                    571:     if (net) {
2.33      frystyk   572:        if (WWWTRACE)
2.31      frystyk   573:            TTYPrint(TDEST,"HTNet_wait.. request %p is waiting for socket %d\n",
2.25      frystyk   574:                    net->request, net->sockfd);
                    575:        if (!HTNetPersistent) HTNetPersistent = HTList_new();
                    576:        HTList_addObject(HTNetPersistent, (void *) net);        
                    577:        return YES;
                    578:     }
                    579:     return NO;
                    580: }
                    581: 
2.23      frystyk   582: /* ------------------------------------------------------------------------- */
                    583: /*                             Killing requests                             */
                    584: /* ------------------------------------------------------------------------- */
                    585: 
                    586: /*     HTNet_kill
                    587: **     ----------
                    588: **     Kill the request by calling the call back function with a request for 
                    589: **     closing the connection. Does not remove the object. This is done by
                    590: **     HTNet_delete() function which is called by the load routine.
                    591: **     Returns OK if success, NO on error
                    592: */
                    593: PUBLIC BOOL HTNet_kill (HTNet * me)
                    594: {
                    595:     if (HTNetActive && me) {
2.25      frystyk   596:        HTList *cur = HTNetActive;
2.23      frystyk   597:        HTNet *pres;
2.25      frystyk   598:        while ((pres = (HTNet *) HTList_nextObject(cur))) {
2.23      frystyk   599:            if (pres == me) {
2.25      frystyk   600:                (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23      frystyk   601:                return YES;
                    602:            }
                    603:        }
                    604:     }
2.33      frystyk   605:     if (WWWTRACE)
2.31      frystyk   606:        TTYPrint(TDEST, "HTNet_kill.. object %p is not registered\n", me);
2.23      frystyk   607:     return NO;
                    608: }
                    609: 
                    610: /*     HTNet_killAll
                    611: **     -------------
                    612: **     Kills all registered (active+pending) requests by calling the call
                    613: **     back function with a request for closing the connection. We do not
                    614: **     remove the HTNet object as it is done by HTNet_delete().
                    615: **     Returns OK if success, NO on error
                    616: */
                    617: PUBLIC BOOL HTNet_killAll (void)
                    618: {
                    619:     HTNet *pres;
2.33      frystyk   620:     if (WWWTRACE)
2.31      frystyk   621:        TTYPrint(TDEST, "HTNet_kill.. ALL registered requests!!!\n");
2.23      frystyk   622: 
2.25      frystyk   623:     /* We start off in persistent queue so we avoid racing */
                    624:     if (HTNetPersistent) {
                    625:        while ((pres = (HTNet *) HTList_lastObject(HTNetPersistent)) != NULL) {
                    626:            pres->sockfd = INVSOC;
                    627:            (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
                    628:            HTList_removeObject(HTNetPersistent, pres);
                    629:        }
                    630:     }
2.23      frystyk   631:     if (HTNetPending) {
                    632:        while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
2.25      frystyk   633:            (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23      frystyk   634:            HTList_removeObject(HTNetPending, pres);
                    635:        }
                    636:     }
                    637:     if (HTNetActive) {
                    638:        while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
2.25      frystyk   639:            (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23      frystyk   640:     }
                    641:     return YES;
                    642: }

Webmaster