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

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

Webmaster