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

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

Webmaster