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

2.23      frystyk     1: /*                                                                  HTNet.c
2.79      frystyk     2: **     HTNet Class
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.
2.106   ! kahan       6: **     @(#) $Id: HTNet.c,v 2.105 2000/06/16 13:44:46 kahan Exp $
2.4       frystyk     7: **
                      8: **     This is the implementation of the internal library multithreading
2.1       frystyk     9: **     functions. This includes an interrupt handler and a event loop.
                     10: **     
                     11: ** History:
2.14      frystyk    12: **     12 June 94      Written by Henrik Frystyk, frystyk@w3.org
2.17      frystyk    13: **      31 May  95      Charlie Brooks cbrooks@osf.org
                     14: **
2.1       frystyk    15: */
                     16: 
2.9       frystyk    17: /* Implemention dependent include files */
2.93      frystyk    18: #include "wwwsys.h"
2.9       frystyk    19: 
2.1       frystyk    20: /* Library include files */
2.59      frystyk    21: #include "WWWUtil.h"
2.16      frystyk    22: #include "HTProt.h"
2.1       frystyk    23: #include "HTError.h"
2.25      frystyk    24: #include "HTAlert.h"
2.37      frystyk    25: #include "HTParse.h"
2.59      frystyk    26: #include "HTTrans.h"
2.74      frystyk    27: #include "HTHost.h"
                     28: #include "HTReq.h"
2.65      frystyk    29: #include "HTEvent.h"
2.23      frystyk    30: #include "HTStream.h"
2.81      frystyk    31: #include "HTHstMan.h"
                     32: #include "HTIOStream.h"
2.24      frystyk    33: #include "HTNetMan.h"                                   /* Implemented here */
2.1       frystyk    34: 
2.23      frystyk    35: #ifndef HT_MAX_SOCKETS
2.93      frystyk    36: #define HT_MAX_SOCKETS 25
2.23      frystyk    37: #endif
                     38: 
2.79      frystyk    39: typedef struct _BeforeFilter {
                     40:     HTNetBefore *      before;                           /* Filter function */
                     41:     char *             tmplate;     /* URL template for when to call filter */
                     42:     int                        order;                   /* Relative execution order */
2.60      frystyk    43:     void *             param;                              /* Local context */
2.79      frystyk    44: } BeforeFilter;
                     45: 
                     46: typedef struct _AfterFilter {
                     47:     HTNetAfter *       after;                            /* Filter function */
                     48:     char *             tmplate;     /* URL template for when to call filter */
                     49:     int                        order;                   /* Relative execution order */
                     50:     void *             param;                              /* Local context */
                     51:     int                        status;    /* Status of load for when to call filter */
                     52: } AfterFilter;
2.23      frystyk    53: 
                     54: struct _HTStream {
2.52      frystyk    55:     const HTStreamClass *      isa;
2.23      frystyk    56:     /* ... */
                     57: };
                     58: 
2.81      frystyk    59: struct _HTInputStream {
                     60:     const HTInputStreamClass * isa;
                     61:     /* ... */
                     62: };
                     63: 
2.99      frystyk    64: typedef struct _HTFilterEvent {
                     65:     HTRequest *                request;
                     66:     int                        status;
                     67:     HTTimer *          timer;
                     68: } HTFilterEvent;
                     69: 
2.79      frystyk    70: PRIVATE HTList * HTBefore = NULL;          /* List of global BEFORE filters */
                     71: PRIVATE HTList * HTAfter = NULL;            /* List of global AFTER filters */
2.24      frystyk    72: 
2.74      frystyk    73: PRIVATE int MaxActive = HT_MAX_SOCKETS;              /* Max active requests */
                     74: PRIVATE int Active = 0;                                      /* Counts open sockets */
                     75: PRIVATE int Persistent = 0;                    /* Counts persistent sockets */
2.1       frystyk    76: 
2.74      frystyk    77: PRIVATE HTList ** NetTable = NULL;                   /* List of net objects */
                     78: PRIVATE int HTNetCount = 0;                   /* Counting elements in table */
2.23      frystyk    79: 
                     80: /* ------------------------------------------------------------------------- */
2.79      frystyk    81: /*                GENERIC BEFORE and AFTER filter Management                */
2.23      frystyk    82: /* ------------------------------------------------------------------------- */
                     83: 
2.79      frystyk    84: PRIVATE int HTBeforeOrder (const void * a, const void * b)
                     85: {
                     86:     return ((BeforeFilter *) b)->order - ((BeforeFilter *) a)->order;
                     87: }
                     88: 
                     89: PRIVATE int HTAfterOrder (const void * a, const void * b)
                     90: {
                     91:     return ((AfterFilter *) b)->order - ((AfterFilter *) a)->order;
                     92: }
                     93: 
2.80      frystyk    94: PRIVATE int check_order (HTFilterOrder order)
2.79      frystyk    95: {
                     96:     return (order<HT_FILTER_FIRST) ? HT_FILTER_FIRST :
                     97:        (order>HT_FILTER_LAST) ? HT_FILTER_LAST : order;
                     98: }
                     99: 
                    100: /*
                    101: **     Register a BEFORE filter in the list provided by the caller.
                    102: **     Several filters can be registered in which case they are called
                    103: **     with the filter ordering in mind.
                    104: */
                    105: PUBLIC BOOL HTNetCall_addBefore (HTList * list, HTNetBefore * before,
                    106:                                 const char * tmplate, void * param, 
2.80      frystyk   107:                                 HTFilterOrder order)
2.79      frystyk   108: {
                    109:     if (list && before) {
                    110:        BeforeFilter * me;
                    111:        if ((me = (BeforeFilter *) HT_CALLOC(1, sizeof(BeforeFilter)))==NULL)
                    112:            HT_OUTOFMEM("HTNetCall_addBefore");
                    113:        me->before = before;
                    114:        if (tmplate) StrAllocCopy(me->tmplate, tmplate);
                    115:        me->order = check_order(order);
                    116:        me->param = param;
2.103     frystyk   117:        HTTRACE(CORE_TRACE, "Net Before.. Add %p with order %d tmplate `%s\' context %p\n" _ 
                    118:                    before _ me->order _ tmplate ? tmplate : "<null>" _ param);
2.79      frystyk   119:        return (HTList_addObject(list, me) &&
                    120:                HTList_insertionSort(list, HTBeforeOrder));
                    121:     }
                    122:     return NO;
                    123: }
                    124: 
                    125: /*
                    126: **     Unregister all instances of a BEFORE filter from a list.
                    127: */
                    128: PUBLIC BOOL HTNetCall_deleteBefore (HTList * list, HTNetBefore * before)
                    129: {
2.103     frystyk   130:     HTTRACE(CORE_TRACE, "Net Before.. Delete %p\n" _ before);
2.79      frystyk   131:     if (list && before) {
                    132:        HTList * cur = list;
                    133:        BeforeFilter * pres;
2.94      frystyk   134:        while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
2.79      frystyk   135:            if (pres->before == before) {
                    136:                HTList_removeObject(list, (void *) pres);
                    137:                HT_FREE(pres->tmplate);
                    138:                HT_FREE(pres);
                    139:                cur = list;
                    140:            }
                    141:        }
                    142:     }
                    143:     return NO;
                    144: }
                    145: 
                    146: /*
                    147: **     Deletes all BEFORE filters in list
                    148: */
                    149: PUBLIC BOOL HTNetCall_deleteBeforeAll (HTList * list)
                    150: {
2.103     frystyk   151:     HTTRACE(CORE_TRACE, "Net Before. Delete All filters\n");
2.79      frystyk   152:     if (list) {
                    153:        HTList * cur = list;
                    154:        BeforeFilter * pres;
                    155:        while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
                    156:            HT_FREE(pres->tmplate);
                    157:            HT_FREE(pres);
                    158:        }
                    159:        HTList_delete(list);
                    160:        return YES;
                    161:     }
                    162:     return NO;
                    163: }
                    164: 
                    165: /*
                    166: **     Call all the BEFORE filters in the order specified at registration
                    167: **     time. We also check for any template and whether it matches or not. 
                    168: **     If a filter returns other than HT_OK then stop and return immediately.
                    169: **     Otherwise return what the last filter returns.
2.23      frystyk   170: */
2.79      frystyk   171: PUBLIC int HTNetCall_executeBefore (HTList * list, HTRequest * request)
2.23      frystyk   172: {
2.79      frystyk   173:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    174:     char * url = HTAnchor_physical(anchor);
                    175:     char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
                    176:     int ret = HT_OK;
                    177:     int mode = 0;    
                    178:     if (list && request && addr) {
                    179:        BeforeFilter * pres;    
                    180:        while ((pres = (BeforeFilter *) HTList_nextObject(list))) {
                    181:            if (!pres->tmplate ||
                    182:                (pres->tmplate && HTStrMatch(pres->tmplate, addr))) {
2.103     frystyk   183:                HTTRACE(CORE_TRACE, "Net Before.. calling %p (request %p, context %p)\n" _ 
                    184:                                        pres->before _ 
                    185:                                        request _ pres->param);
2.79      frystyk   186:                ret = (*pres->before)(request, pres->param, mode);
                    187:                if (ret != HT_OK) break;
2.88      frystyk   188: 
                    189:                /*
                    190:                **  Update the address to match against if the filter changed
                    191:                **  the physical address.
                    192:                */
                    193:                if ((url = HTAnchor_physical(anchor))) addr = url;
2.79      frystyk   194:            }
                    195:        }
                    196:     }
                    197:     if (!url) HT_FREE(addr);
                    198:     return ret;
                    199: }
                    200: 
                    201: /*
2.106   ! kahan     202: **     Register an AFTER filter in the list provided by the caller.
2.79      frystyk   203: **     Several filters can be registered in which case they are called
                    204: **     with the filter ordering in mind.
                    205: */
                    206: PUBLIC BOOL HTNetCall_addAfter (HTList * list, HTNetAfter * after,
                    207:                                const char * tmplate, void * param,
2.80      frystyk   208:                                int status, HTFilterOrder order)
2.79      frystyk   209: {
                    210:     if (list && after) {
                    211:        AfterFilter * me;
                    212:        if ((me = (AfterFilter *) HT_CALLOC(1, sizeof(AfterFilter)))==NULL)
                    213:            HT_OUTOFMEM("HTNetCall_addAfter");
                    214:        me->after = after;
                    215:        if (tmplate) StrAllocCopy(me->tmplate, tmplate);
                    216:        me->order = check_order(order);
2.60      frystyk   217:        me->param = param;
2.33      frystyk   218:        me->status = status;
2.103     frystyk   219:        HTTRACE(CORE_TRACE, "Net After... Add %p with order %d tmplate `%s\' code %d context %p\n" _ 
                    220:                    after _ me->order _ tmplate ? tmplate : "<null>" _ status _ param);
2.79      frystyk   221:        return (HTList_addObject(list, me) &&
                    222:                HTList_insertionSort(list, HTAfterOrder));
                    223:     }
                    224:     return NO;
                    225: }
                    226: 
                    227: /*
                    228: **     Unregister all instances of an AFTER filter from a list.
                    229: */
                    230: PUBLIC BOOL HTNetCall_deleteAfter (HTList * list, HTNetAfter * after)
                    231: {
2.103     frystyk   232:     HTTRACE(CORE_TRACE, "Net After... Delete %p\n" _ after);
2.79      frystyk   233:     if (list && after) {
                    234:        HTList * cur = list;
                    235:        AfterFilter * pres;
                    236:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    237:            if (pres->after == after) {
                    238:                HTList_removeObject(list, (void *) pres);
                    239:                HT_FREE(pres->tmplate);
                    240:                HT_FREE(pres);
                    241:                cur = list;
                    242:            }
                    243:        }
2.23      frystyk   244:     }
                    245:     return NO;
                    246: }
                    247: 
2.79      frystyk   248: /*
                    249: **     Unregister all filters registered for a given status.
2.23      frystyk   250: */
2.79      frystyk   251: PUBLIC BOOL HTNetCall_deleteAfterStatus (HTList * list, int status)
2.23      frystyk   252: {
2.103     frystyk   253:     HTTRACE(CORE_TRACE, "Net After... Delete all with status %d\n" _ status);
2.79      frystyk   254:     if (list) {
                    255:        HTList * cur = list;
                    256:        AfterFilter * pres;
                    257:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    258:            if (pres->status == status) {
2.33      frystyk   259:                HTList_removeObject(list, (void *) pres);
2.79      frystyk   260:                HT_FREE(pres->tmplate);
2.49      frystyk   261:                HT_FREE(pres);
2.79      frystyk   262:                cur = list;
2.23      frystyk   263:            }
                    264:        }
2.79      frystyk   265:        return YES;
2.23      frystyk   266:     }
                    267:     return NO;
                    268: }
2.1       frystyk   269: 
2.79      frystyk   270: /*
                    271: **     Deletes all AFTER filters in list
2.23      frystyk   272: */
2.79      frystyk   273: PUBLIC BOOL HTNetCall_deleteAfterAll (HTList * list)
2.23      frystyk   274: {
2.103     frystyk   275:     HTTRACE(CORE_TRACE, "Net After. Delete All filters\n");
2.33      frystyk   276:     if (list) {
2.79      frystyk   277:        HTList * cur = list;
                    278:        AfterFilter * pres;
                    279:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    280:            HT_FREE(pres->tmplate);
2.49      frystyk   281:            HT_FREE(pres);
2.23      frystyk   282:        }
2.33      frystyk   283:        HTList_delete(list);
2.23      frystyk   284:        return YES;
                    285:     }
                    286:     return NO;
                    287: }
                    288: 
2.79      frystyk   289: /*
                    290: **     Call all the AFTER filters in the order specified at registration
                    291: **     time and if it has the right status code and it's not HT_IGNORE.
                    292: **     We also check for any template and whether it matches or not.
                    293: **     If a filter returns other than HT_OK then stop and return immediately.
                    294: **     Otherwise return what the last filter returns.
2.23      frystyk   295: */
2.79      frystyk   296: PUBLIC int HTNetCall_executeAfter (HTList * list, HTRequest * request,
                    297:                                   int status)
2.23      frystyk   298: {
2.33      frystyk   299:     int ret = HT_OK;
2.79      frystyk   300:     if (status != HT_IGNORE) {
                    301:        HTParentAnchor * anchor = HTRequest_anchor(request);
                    302:        char * url = HTAnchor_physical(anchor);
                    303:        char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
                    304:        HTResponse * response = HTRequest_response(request);
                    305:        if (list && request && addr) {
                    306:            AfterFilter * pres;
                    307:            while ((pres = (AfterFilter *) HTList_nextObject(list))) {
                    308:                if ((pres->status == status || pres->status == HT_ALL) &&
                    309:                    (!pres->tmplate ||
                    310:                     (pres->tmplate && HTStrMatch(pres->tmplate, addr)))) {
2.103     frystyk   311:                    HTTRACE(CORE_TRACE, "Net After... calling %p (request %p, response %p, status %d, context %p)\n" _ 
                    312:                                pres->after _ request _ response _ 
                    313:                                status _ pres->param);
2.79      frystyk   314:                    ret = (*pres->after)(request, response, pres->param, status);
                    315:                    if (ret != HT_OK) break;
2.88      frystyk   316: 
                    317:                    /*
                    318:                    **  Update the address to match against if the filter changed
                    319:                    **  the physical address.
                    320:                    */
                    321:                    if ((url = HTAnchor_physical(anchor))) addr = url;
2.79      frystyk   322:                }
2.23      frystyk   323:            }
                    324:        }
2.79      frystyk   325:        if (!url) HT_FREE(addr);
2.1       frystyk   326:     }
2.33      frystyk   327:     return ret;
                    328: }
                    329: 
2.79      frystyk   330: /* ------------------------------------------------------------------------- */
                    331: /*                GLOBAL BEFORE and AFTER filter Management                 */
                    332: /* ------------------------------------------------------------------------- */
                    333: 
2.33      frystyk   334: /*
                    335: **     Global set of callback functions BEFORE the request is issued
                    336: **     list can be NULL
                    337: */
                    338: PUBLIC BOOL HTNet_setBefore (HTList *list)
                    339: {
                    340:     HTBefore = list;
                    341:     return YES;
                    342: }
                    343: 
                    344: PUBLIC HTList * HTNet_before (void)
                    345: {
                    346:     return HTBefore;
                    347: }
                    348: 
2.79      frystyk   349: PUBLIC BOOL HTNet_addBefore (HTNetBefore * before, const char * tmplate,
2.80      frystyk   350:                             void * param, HTFilterOrder order)
2.33      frystyk   351: {
2.79      frystyk   352:     if (!HTBefore) HTBefore = HTList_new();
                    353:     return HTNetCall_addBefore(HTBefore, before, tmplate, param, order);
2.33      frystyk   354: }
                    355: 
2.79      frystyk   356: PUBLIC BOOL HTNet_deleteBefore (HTNetBefore * cbf)
2.33      frystyk   357: {
2.79      frystyk   358:     return HTNetCall_deleteBefore(HTBefore, cbf);
2.33      frystyk   359: }
                    360: 
2.79      frystyk   361: /*
                    362: **  Call both the local and the global BEFORE filters (if any)
                    363: */
                    364: PUBLIC int HTNet_executeBeforeAll (HTRequest * request)
2.73      frystyk   365: {
2.79      frystyk   366:     int ret;
                    367:     BOOL override = NO;
                    368:     HTList * befores;
                    369:     if ((befores = HTRequest_before(request, &override))) {
                    370:        if ((ret = HTNetCall_executeBefore(befores, request)) != HT_OK)
                    371:            return ret;
                    372:     }
                    373:     return override ? HT_OK : HTNetCall_executeBefore(HTBefore, request);
2.73      frystyk   374: }
                    375: 
2.33      frystyk   376: /*
                    377: **     Global set of callback functions AFTER the request is issued
                    378: **     list can be NULL
                    379: */
                    380: PUBLIC BOOL HTNet_setAfter (HTList *list)
                    381: {
                    382:     HTAfter = list;
                    383:     return YES;
                    384: }
                    385: 
                    386: PUBLIC HTList * HTNet_after (void)
                    387: {
                    388:     return HTAfter;
                    389: }
                    390: 
2.79      frystyk   391: PUBLIC BOOL HTNet_addAfter (HTNetAfter * after, const char * tmplate,
2.80      frystyk   392:                            void * param, int status, HTFilterOrder order)
2.33      frystyk   393: {
2.79      frystyk   394:     if (!HTAfter) HTAfter = HTList_new();
                    395:     return HTNetCall_addAfter(HTAfter, after, tmplate, param, status, order);
                    396: }
2.58      hallam    397: 
2.79      frystyk   398: PUBLIC BOOL HTNet_deleteAfter (HTNetAfter * cbf)
                    399: {
                    400:     return HTNetCall_deleteAfter(HTAfter, cbf);
2.33      frystyk   401: }
                    402: 
2.79      frystyk   403: PUBLIC BOOL HTNet_deleteAfterStatus (int status)
2.33      frystyk   404: {
2.79      frystyk   405:     return HTNetCall_deleteAfterStatus(HTAfter, status);
2.73      frystyk   406: }
                    407: 
2.79      frystyk   408: /*
                    409: **  Call both the local and the global AFTER filters (if any)
                    410: */
                    411: PUBLIC int HTNet_executeAfterAll (HTRequest * request, int status)
2.73      frystyk   412: {
2.79      frystyk   413:     int ret;
                    414:     BOOL override = NO;
                    415:     HTList * afters;
                    416:     if ((afters = HTRequest_after(request, &override))) {
                    417:        if ((ret = HTNetCall_executeAfter(afters, request, status)) != HT_OK)
                    418:            return ret;
                    419:     }
                    420:     return override ? HT_OK : HTNetCall_executeAfter(HTAfter, request, status);
2.1       frystyk   421: }
                    422: 
2.23      frystyk   423: /* ------------------------------------------------------------------------- */
2.74      frystyk   424: /*                           Socket Management                              */
2.23      frystyk   425: /* ------------------------------------------------------------------------- */
2.1       frystyk   426: 
2.74      frystyk   427: PUBLIC int HTNet_maxSocket (void)
                    428: {
                    429:     return MaxActive;
                    430: }
                    431: 
                    432: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
                    433: {
                    434:     if (newmax > 0) {
                    435:        MaxActive = newmax;
                    436:        return YES;
                    437:     }
                    438:     return NO;
                    439: }
                    440: 
                    441: PUBLIC void HTNet_increaseSocket (void)
                    442: {
                    443:     Active++;
2.103     frystyk   444:     HTTRACE(CORE_TRACE, "Net Manager. Increasing active sockets to %d, %d persistent sockets\n" _ 
                    445:                Active _ Persistent);
2.74      frystyk   446: }
                    447: 
                    448: PUBLIC void HTNet_decreaseSocket (void)
                    449: {
                    450:     if (--Active < 0) Active = 0;
2.103     frystyk   451:     HTTRACE(CORE_TRACE, "Net Manager. Decreasing active sockets to %d, %d persistent sockets\n" _ 
                    452:                Active _ Persistent);
2.74      frystyk   453: }
                    454: 
                    455: PUBLIC int HTNet_availableSockets (void)
                    456: {
                    457:     int available = MaxActive - Active;
                    458:     return available > 0 ? available : 0;
                    459: }
                    460: 
                    461: PUBLIC void HTNet_increasePersistentSocket (void)
                    462: {
                    463:     Persistent++;
2.103     frystyk   464:     HTTRACE(CORE_TRACE, "Net Manager. %d active sockets, increasing persistent sockets to %d\n" _ 
                    465:                Active _ Persistent);
2.74      frystyk   466: }
                    467: 
                    468: PUBLIC void HTNet_decreasePersistentSocket (void)
2.23      frystyk   469: {
2.74      frystyk   470:     if (--Persistent < 0) Persistent = 0;
2.103     frystyk   471:     HTTRACE(CORE_TRACE, "Net Manager. %d active sockets, decreasing persistent sockets to %d\n" _ 
                    472:                Active _ Persistent);
2.23      frystyk   473: }
2.17      frystyk   474: 
2.74      frystyk   475: PUBLIC int HTNet_availablePersistentSockets (void)
2.28      frystyk   476: {
2.74      frystyk   477:     int available = MaxActive - 2 - Persistent;
                    478:     return available > 0 ? available : 0;
2.28      frystyk   479: }
                    480: 
2.74      frystyk   481: /*
                    482: **     Returns whether there are any Net objects pending or active
2.40      frystyk   483: */
2.74      frystyk   484: PUBLIC BOOL HTNet_isIdle (void)
2.40      frystyk   485: {
2.74      frystyk   486:     return (HTNetCount > 0);
2.40      frystyk   487: }
                    488: 
2.74      frystyk   489: PUBLIC BOOL HTNet_isEmpty (void)
2.1       frystyk   490: {
2.74      frystyk   491:     return (HTNetCount <= 0);
2.1       frystyk   492: }
                    493: 
2.81      frystyk   494: PUBLIC int HTNet_count (void)
                    495: {
                    496:     return HTNetCount;
                    497: }
                    498: 
2.23      frystyk   499: /* ------------------------------------------------------------------------- */
                    500: /*                       Creation and deletion methods                      */
                    501: /* ------------------------------------------------------------------------- */
                    502: 
2.99      frystyk   503: PRIVATE int AfterFilterEvent (HTTimer * timer, void * param, HTEventType type)
                    504: {
                    505:     HTFilterEvent * fe = (HTFilterEvent *) param;
                    506:     if (fe) {
                    507:        HTRequest * request = fe->request;
                    508:        int status = fe->status;
                    509:        if (timer != fe->timer)
2.103     frystyk   510:            HTDEBUGBREAK("Net timer. %p not in sync\n" _ timer);
                    511:        HTTRACE(CORE_TRACE, "HTNet....... Continuing calling AFTER filters %p with timer %p\n" _ 
                    512:                    fe _ timer);
2.99      frystyk   513: 
                    514:        /* Delete the event context */
                    515:        HT_FREE(fe);
                    516: 
                    517:        /* Now call the remaining AFTER filters */
                    518:        return HTNet_executeAfterAll(request, status);
                    519:     }
                    520:     return HT_ERROR;
                    521: }
                    522: 
                    523: PRIVATE BOOL createAfterFilterEvent (HTRequest * request, int status)
                    524: {
                    525:     HTFilterEvent * me = NULL;
                    526:     if ((me = (HTFilterEvent *) HT_CALLOC(1, sizeof(HTFilterEvent))) == NULL)
                    527:         HT_OUTOFMEM("createAfterFilterEvent");
                    528:     me->request = request;
                    529:     me->status = status;
                    530:     me->timer = HTTimer_new(NULL, AfterFilterEvent, me, 1, YES, NO);
                    531:     return YES;
                    532: }
                    533: 
2.74      frystyk   534: PRIVATE HTNet * create_object (void)
                    535: {
                    536:     static int net_hash = 0;
                    537:     HTNet * me = NULL;
                    538: 
                    539:     /* Create new object */
                    540:     if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
                    541:         HT_OUTOFMEM("HTNet_new");
2.100     frystyk   542:     me->hash = net_hash++ % HT_XL_HASH_SIZE;
2.74      frystyk   543: 
                    544:     /* Insert into hash table */
                    545:     if (!NetTable) {
2.100     frystyk   546:        if ((NetTable = (HTList **) HT_CALLOC(HT_XL_HASH_SIZE, sizeof(HTList *))) == NULL)
2.74      frystyk   547:            HT_OUTOFMEM("create_object");
                    548:     }
                    549:     if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new();
                    550:     HTList_addObject(NetTable[me->hash], (void *) me);
                    551:     HTNetCount++;
2.103     frystyk   552:     HTTRACE(CORE_TRACE, "Net Object.. %p created with hash %d\n" _ me _ me->hash);
2.74      frystyk   553:     return me;
                    554: }
                    555: 
2.27      frystyk   556: /*     HTNet_duplicate
                    557: **     ---------------
                    558: **     Creates a new HTNet object as a duplicate of the same request.
                    559: **     Returns YES if OK, else NO
                    560: **     BUG: We do not check if we have a socket free!
                    561: */
2.43      frystyk   562: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27      frystyk   563: {
2.74      frystyk   564:     if (src) {
                    565:         HTNet * me;
2.75      frystyk   566:        int hash;
2.74      frystyk   567:        if ((me = create_object()) == NULL) return NULL;
2.75      frystyk   568:        hash = me->hash;
2.103     frystyk   569:        HTTRACE(CORE_TRACE, "Net Object.. Duplicated %p\n" _ src);
2.74      frystyk   570:         memcpy((void *) me, src, sizeof(HTNet));
2.75      frystyk   571:        me->hash = hash;                        /* Carry over hash entry */
2.74      frystyk   572:        return me;
                    573:     }
                    574:     return NULL;
2.27      frystyk   575: }
                    576: 
2.81      frystyk   577: PUBLIC BOOL HTNet_execute (HTNet * net, HTEventType type)
                    578: {
                    579:     if (net && net->event.cbf && net->request) {
2.103     frystyk   580:        HTTRACE(CORE_TRACE, "Net Object.. %p calling %p with event type %d and context %p\n" _ 
                    581:                    net _ net->event.cbf _ type _ net->event.param);
2.82      frystyk   582:        (*(net->event.cbf))(HTNet_socket(net), net->event.param, type);
2.81      frystyk   583:        return YES;
                    584:     }
                    585:     return NO;
                    586: }
                    587: 
2.74      frystyk   588: /*
                    589: **     Start a Net obejct by calling the protocol module.
2.30      frystyk   590: */
2.74      frystyk   591: PUBLIC BOOL HTNet_start (HTNet * net)
2.30      frystyk   592: {
2.81      frystyk   593:     if (net && net->event.cbf && net->request) {
2.103     frystyk   594:        HTTRACE(CORE_TRACE, "Net Object.. Launching %p\n" _ net);
2.81      frystyk   595:        (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_BEGIN);
2.30      frystyk   596:        return YES;
                    597:     }
                    598:     return NO;
                    599: }
                    600: 
2.37      frystyk   601: /*     HTNet_new
                    602: **     ---------
                    603: **     This function creates a new HTNet object and assigns the socket number
                    604: **     to it. This is intended to be used when you are going to listen on a 
                    605: **     socket using the HTDoListen() function in HTTCP.c. The function do NOT
2.104     frystyk   606: **     call any of the before or after filter functions.
2.37      frystyk   607: **     Returns new object or NULL on error
                    608: */
2.104     frystyk   609: PUBLIC HTNet * HTNet_new (HTHost * host)
2.37      frystyk   610: {
2.104     frystyk   611:     if (host) {
                    612:        HTNet * me;
                    613:        HTTRACE(CORE_TRACE, "Net Object.. Creating listen object for host %p\n" _ host);
                    614:        me = create_object();
                    615:        me->host = host;
                    616:        return me;
                    617:     }
                    618:     return NULL;
2.37      frystyk   619: }
                    620: 
2.67      frystyk   621: /*      HTNet_newServer
                    622: **      ---------------
                    623: **      Create a new HTNet object as a new request to be handled. If we have
2.74      frystyk   624: **      more than MaxActive connections already then return NO.
2.67      frystyk   625: **      Returns YES if OK, else NO
2.37      frystyk   626: */
2.98      frystyk   627: PUBLIC BOOL HTNet_newServer (HTRequest * request)
2.37      frystyk   628: {
2.98      frystyk   629:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    630:     HTNet * me = NULL;
2.37      frystyk   631:     HTProtocol * protocol;
2.67      frystyk   632:     HTTransport * tp = NULL;           /* added JTD:5/28/96 */
2.98      frystyk   633:     char * physical = NULL;
                    634:     int status;
2.81      frystyk   635:     HTProtCallback * cbf;
2.98      frystyk   636: 
2.37      frystyk   637:     if (!request) return NO;
                    638: 
2.98      frystyk   639:     /*
                    640:     ** First we do all the "BEFORE" callbacks in order to see if we are to
                    641:     ** continue with this request or not. If we receive a callback status
                    642:     ** that is NOT HT_OK then jump directly to the after callbacks and return
                    643:     */
                    644:     if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99      frystyk   645: 
                    646:        /*
                    647:        **  If in non-blocking mode then return here and call AFTER
                    648:        **  filters from a timer event handler. As Olga Antropova
                    649:        **  points out, otherwise, the stack can grow if new requests
                    650:        **  are started directly from the after filters 
                    651:        */
                    652:        if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
                    653:            createAfterFilterEvent(request, status);
                    654:        else
                    655:            HTNet_executeAfterAll(request, status);
2.98      frystyk   656:        return YES;
                    657:     }
                    658: 
                    659:     /*
                    660:     ** If no translation was provided by the filters then use the anchor
                    661:     ** address directly
                    662:     */
                    663:     if (!(physical = HTAnchor_physical(anchor))) {
                    664:        char * addr = HTAnchor_address((HTAnchor *) anchor);
2.103     frystyk   665:        HTTRACE(CORE_TRACE, "Net Object.. Using default address\n");
2.98      frystyk   666:        HTAnchor_setPhysical(anchor, addr);
                    667:        physical = HTAnchor_physical(anchor);
                    668:        HT_FREE(addr);
                    669:     }
                    670: 
2.37      frystyk   671:     /* Find a protocol object for this access scheme */
2.98      frystyk   672:     {
                    673:        char * access = HTParse(physical, "", PARSE_ACCESS);      
                    674:        if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.103     frystyk   675:            HTTRACE(CORE_TRACE, "Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n" _ access);
2.98      frystyk   676:            HT_FREE(access);
                    677:            return NO;
                    678:        }
                    679:        if (!(cbf = HTProtocol_server(protocol))) {
2.103     frystyk   680:            HTTRACE(CORE_TRACE, "Net Object.. NO SERVER HANDLER for URI scheme `%s\'\n" _ access);
2.98      frystyk   681:            HT_FREE(access);
                    682:            HT_FREE(me);
                    683:            return NO;
                    684:        }
                    685:        HT_FREE(access);
                    686:     }
2.67      frystyk   687: 
                    688:     /* Find a transport object for this protocol */
2.98      frystyk   689:     if ((tp = HTTransport_find(request, HTProtocol_transport(protocol))) == NULL) {
2.103     frystyk   690:         HTTRACE(CORE_TRACE, "Net Object.. NO TRANSPORT found for protocol `%s\'\n" _ HTProtocol_name(protocol));
2.67      frystyk   691:         return NO;
                    692:     }
                    693: 
2.98      frystyk   694:     /* Create new net object and bind to request object */
                    695:     if ((me = create_object()) == NULL) return NO;
                    696:     me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
                    697:     HTNet_setEventPriority(me, HTRequest_priority(request));
                    698:     me->protocol = protocol;
                    699:     me->transport = tp;                /* added - JTD:5/28/96 */
                    700:     me->request = request;
                    701:     HTRequest_setNet(request, me);
2.37      frystyk   702: 
                    703:     /* Start the server request */
2.103     frystyk   704:     HTTRACE(CORE_TRACE, "Net Object.. starting SERVER request %p and net object %p\n" _ request _ me);
2.98      frystyk   705:     (*(cbf))(INVSOC, request);
2.37      frystyk   706:     return YES;
                    707: }
2.36      frystyk   708: 
2.104     frystyk   709: /*     HTNet_newClient
                    710: **     ---------------
2.23      frystyk   711: **     Create a new HTNet object as a new request to be handled. If we have
2.74      frystyk   712: **     more than MaxActive connections already then put this into the
2.23      frystyk   713: **     pending queue, else start the request by calling the call back
                    714: **     function registered with this access method. 
                    715: **     Returns YES if OK, else NO
                    716: */
2.37      frystyk   717: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23      frystyk   718: {
2.74      frystyk   719:     HTParentAnchor * anchor = HTRequest_anchor(request);
2.59      frystyk   720:     HTNet * me = NULL;
                    721:     HTProtocol * protocol = NULL;
                    722:     HTTransport * tp = NULL;
2.37      frystyk   723:     char * physical = NULL;
2.74      frystyk   724:     int status;
2.81      frystyk   725:     HTProtCallback * cbf;
                    726: 
2.27      frystyk   727:     if (!request) return NO;
2.98      frystyk   728: 
2.33      frystyk   729:     /*
                    730:     ** First we do all the "BEFORE" callbacks in order to see if we are to
                    731:     ** continue with this request or not. If we receive a callback status
                    732:     ** that is NOT HT_OK then jump directly to the after callbacks and return
                    733:     */
2.79      frystyk   734:     if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99      frystyk   735: 
                    736:        /*
                    737:        **  If in non-blocking mode then return here and call AFTER
                    738:        **  filters from a timer event handler. As Olga Antropova
                    739:        **  points out, otherwise, the stack can grow if new requests
                    740:        **  are started directly from the after filters 
                    741:        */
                    742:        if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
                    743:            createAfterFilterEvent(request, status);
                    744:        else
                    745:            HTNet_executeAfterAll(request, status);
2.33      frystyk   746:        return YES;
                    747:     }
                    748: 
2.36      frystyk   749:     /*
2.79      frystyk   750:     ** If no translation was provided by the filters then use the anchor
2.36      frystyk   751:     ** address directly
                    752:     */
2.74      frystyk   753:     if (!(physical = HTAnchor_physical(anchor))) {
                    754:        char * addr = HTAnchor_address((HTAnchor *) anchor);
2.103     frystyk   755:        HTTRACE(CORE_TRACE, "Net Object.. Using default address\n");
2.74      frystyk   756:        HTAnchor_setPhysical(anchor, addr);
                    757:        physical = HTAnchor_physical(anchor);
2.49      frystyk   758:        HT_FREE(addr);
2.33      frystyk   759:     }
                    760: 
2.37      frystyk   761:     /* Find a protocol object for this access scheme */
                    762:     {
2.81      frystyk   763:        char * proxy = HTRequest_proxy(request);
                    764:        char * access = HTParse(proxy ? proxy : physical, "", PARSE_ACCESS);      
2.37      frystyk   765:        if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.103     frystyk   766:            HTTRACE(CORE_TRACE, "Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n" _ access);
2.49      frystyk   767:            HT_FREE(access);
2.37      frystyk   768:            return NO;
                    769:        }
2.98      frystyk   770:        if (!(cbf = HTProtocol_client(protocol))) {
2.103     frystyk   771:            HTTRACE(CORE_TRACE, "Net Object.. NO CLIENT HANDLER for URI scheme `%s\'\n" _ access);
2.98      frystyk   772:            HT_FREE(access);
                    773:            HT_FREE(me);
                    774:            return NO;
                    775:        }
2.49      frystyk   776:        HT_FREE(access);
2.37      frystyk   777:     }
2.59      frystyk   778: 
                    779:     /* Find a transport object for this protocol */
                    780:     tp = HTTransport_find(request, HTProtocol_transport(protocol));
                    781:     if (tp == NULL) {
2.103     frystyk   782:        HTTRACE(CORE_TRACE, "Net Object.. NO TRANSPORT found for protocol `%s\'\n" _ HTProtocol_name(protocol));
2.59      frystyk   783:        return NO;
                    784:     }
                    785: 
2.23      frystyk   786:     /* Create new net object and bind it to the request object */
2.69      frystyk   787:     if ((me = create_object()) == NULL) return NO;
2.74      frystyk   788:     me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.81      frystyk   789: #if 0
2.69      frystyk   790:     me->priority = HTRequest_priority(request);
2.81      frystyk   791: #endif
                    792:     HTNet_setEventPriority(me, HTRequest_priority(request));
2.59      frystyk   793:     me->protocol = protocol;
                    794:     me->transport = tp;
2.69      frystyk   795:     me->request = request;
                    796:     HTRequest_setNet(request, me);
2.74      frystyk   797: 
                    798:     /* Increase the number of retrys for this download */
                    799:     HTRequest_addRetry(request);
2.23      frystyk   800: 
                    801:     /*
                    802:     ** Check if we can start the request, else put it into pending queue
                    803:     ** If so then call the call back function associated with the anchor.
                    804:     ** We use the INVSOC as we don't have a valid socket yet!
                    805:     */
2.103     frystyk   806:     HTTRACE(CORE_TRACE, "Net Object.. starting request %p (retry=%d) with net object %p\n" _ 
                    807:                request _ HTRequest_retrys(request) _ me);
2.81      frystyk   808:     (*(cbf))(INVSOC, request);
2.36      frystyk   809:     return YES;
                    810: }
                    811: 
2.101     frystyk   812: /*
                    813: **      Check whether we have any pending HTNet objects and if so
                    814: **     then start the next one.
2.40      frystyk   815: **     Return YES if OK, else NO
2.15      frystyk   816: */
2.101     frystyk   817: PRIVATE BOOL check_pending (HTNet * net)
2.15      frystyk   818: {
2.103     frystyk   819:     HTTRACE(CORE_TRACE, "Net Object.. Check for pending Net objects\n");
2.23      frystyk   820:     if (net) {
                    821: 
2.74      frystyk   822:        /*
                    823:        **  As we may have a socket available we check for whether
                    824:        **  we can start any pending requests. We do this by asking for
                    825:        **  pending Host objects. If none then use the current object
                    826:        */
2.101     frystyk   827:         HTHost_launchPending(net->host);
2.74      frystyk   828: 
2.101     frystyk   829:         return YES;
                    830:     }
                    831:     return NO;
                    832: }
2.89      frystyk   833: 
2.101     frystyk   834: PRIVATE BOOL free_net (HTNet * net)
                    835: {
2.103     frystyk   836:     HTTRACE(CORE_TRACE, "Net Object.. Freeing object %p\n" _ net);
2.101     frystyk   837:     if (net) {
2.104     frystyk   838:         if (net == HTRequest_net(net->request)) HTRequest_setNet(net->request, NULL);
2.101     frystyk   839:         HT_FREE(net);
2.81      frystyk   840:        return YES;
                    841:     }
                    842:     return NO;
                    843: }
                    844: 
2.101     frystyk   845: /*
                    846: **  Unregister the net object from the global list
                    847: **  and see if we can start a new pending request.
                    848: */
                    849: PRIVATE BOOL unregister_net (HTNet * net)
2.81      frystyk   850: {
                    851:     if (net && NetTable) {
                    852:        HTList * list = NetTable[net->hash];
                    853:        if (list) {
                    854:            HTList_removeObject(list, (void *) net);
2.101     frystyk   855:            check_pending(net);
2.81      frystyk   856:            HTNetCount--;
                    857:            return YES;
                    858:        }
2.23      frystyk   859:     }
                    860:     return NO;
                    861: }
                    862: 
2.74      frystyk   863: /*
                    864: **     Clears the contents of the Net object so that we can use it again.
                    865: */
                    866: PUBLIC BOOL HTNet_clear (HTNet * net)
                    867: {
                    868:     if (net) {
2.81      frystyk   869:        net->host->channel = NULL;
                    870:        net->readStream = NULL;
                    871:        net->bytesRead = 0;
2.95      frystyk   872:        net->headerBytesRead = 0;
2.81      frystyk   873:        net->bytesWritten = 0;
2.95      frystyk   874:        net->headerBytesWritten = 0;
2.74      frystyk   875:        return YES;
                    876:     }
                    877:     return NO;
                    878: }
                    879: 
2.23      frystyk   880: /*     HTNet_delete
                    881: **     ------------
                    882: **     Deletes the HTNet object from the list of active requests and calls
                    883: **     any registered call back functions IF not the status is HT_IGNORE.
                    884: **     This is used if we have internal requests that the app doesn't know
                    885: **     about. We also see if we have pending requests that can be started
                    886: **     up now when we have a socket free.
                    887: **     The callback functions are called in the reverse order of which they
                    888: **     were registered (last one first)
2.40      frystyk   889: **     Return YES if OK, else NO
2.23      frystyk   890: */
                    891: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
                    892: {
2.103     frystyk   893:     HTTRACE(CORE_TRACE, "Net Object.. Delete %p and call AFTER filters\n" _ net);
2.74      frystyk   894:     if (net) {
                    895:        HTRequest * request = net->request;
2.23      frystyk   896: 
2.25      frystyk   897:        /*
2.74      frystyk   898:        ** If we have a premature close then recover the request. Otherwise
                    899:        ** break the link to the Host object and continue deleting the net
                    900:        ** object
2.25      frystyk   901:        */
2.74      frystyk   902:        if (net->host) {
2.81      frystyk   903:            HTHost_unregister (net->host, net, HTEvent_READ);
                    904:            HTHost_unregister (net->host, net, HTEvent_WRITE);
2.74      frystyk   905:            if (status == HT_RECOVER_PIPE) {
                    906:                HTNet_clear(net);
2.103     frystyk   907:                HTTRACE(CORE_TRACE, "Net Object.. Restarting request %p (retry=%d) with net object %p\n" _ 
                    908:                            request _ HTRequest_retrys(request) _ net);
2.74      frystyk   909:                return YES;
2.81      frystyk   910:            }
2.97      frystyk   911:             HTHost_deleteNet(net->host, net, status);
2.92      frystyk   912:            if (HTHost_doRecover(net->host)) HTHost_recoverPipe(net->host);
2.89      frystyk   913:         }
2.74      frystyk   914: 
                    915:         /* Remove object from the table of Net Objects */
2.101     frystyk   916:        unregister_net(net);
2.102     frystyk   917:         free_net(net);
2.82      frystyk   918: 
2.74      frystyk   919:        /* Call AFTER filters */
2.104     frystyk   920:        if (status != HT_IGNORE) HTNet_executeAfterAll(request, status);
2.101     frystyk   921:         
                    922:        /*
                    923:        ** Truely delete the HTNet object. Thanks to Mikhail Grouchinski
                    924:        ** we now do this after having called the after filters so that
                    925:        ** these filters can use the information in the Net object
                    926:        */
                    927: 
                    928:        return YES;
2.23      frystyk   929:     }
                    930:     return NO;
2.98      frystyk   931: }
                    932: 
                    933: PUBLIC BOOL HTNet_deleteDup (HTNet * dup)
                    934: {
2.101     frystyk   935:     return dup ? (unregister_net(dup) && free_net(dup)) : NO;
2.23      frystyk   936: }
                    937: 
                    938: /*     HTNet_deleteAll
                    939: **     ---------------
                    940: **     Deletes all HTNet object that might either be active or pending
2.74      frystyk   941: **     We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23      frystyk   942: */
                    943: PUBLIC BOOL HTNet_deleteAll (void)
                    944: {
2.103     frystyk   945:     HTTRACE(CORE_TRACE, "Net Object.. Remove all Net objects, NO filters\n"); 
2.74      frystyk   946:     if (NetTable) {
                    947:        HTList * cur = NULL;
                    948:         HTNet * pres = NULL;
                    949:        int cnt;
2.100     frystyk   950:        for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74      frystyk   951:            if ((cur = NetTable[cnt])) { 
2.101     frystyk   952:                while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)  {
                    953:                    check_pending(pres);
                    954:                     free_net(pres);
                    955:                }
2.74      frystyk   956:            }
                    957:            HTList_delete(NetTable[cnt]);
2.25      frystyk   958:        }
2.74      frystyk   959:        HT_FREE(NetTable);
                    960:        HTNetCount = 0;
                    961:        return YES;
2.25      frystyk   962:     }
                    963:     return NO;
2.97      frystyk   964: }
                    965: 
                    966: /*
                    967: **     When pipelining, it is not possible to kill a single request 
                    968: **     as we then loose track of where we are in the pipe. It is 
                    969: **     therefore necessary to kill the whole pipeline.
                    970: */
                    971: PUBLIC BOOL HTNet_killPipe (HTNet * net)
                    972: {
                    973:     return (net && net->host) ? HTHost_killPipe(net->host) : NO;
2.25      frystyk   974: }
                    975: 
2.23      frystyk   976: /*     HTNet_kill
                    977: **     ----------
                    978: **     Kill the request by calling the call back function with a request for 
                    979: **     closing the connection. Does not remove the object. This is done by
                    980: **     HTNet_delete() function which is called by the load routine.
                    981: **     Returns OK if success, NO on error
                    982: */
2.74      frystyk   983: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23      frystyk   984: {
2.81      frystyk   985:     if (net) {
2.94      frystyk   986:         HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);
                    987:         if (cbf) (*cbf)(net->request, HT_PROG_INTERRUPT, HT_MSG_NULL, NULL, NULL, NULL);
2.103     frystyk   988:        HTTRACE(CORE_TRACE, "Net Object.. Killing %p\n" _ net);
2.81      frystyk   989:        if (net->event.cbf) {
                    990:            (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_CLOSE);
                    991:            return YES;
                    992:        }
2.101     frystyk   993:        return unregister_net(net) && free_net(net);
2.23      frystyk   994:     }
2.103     frystyk   995:     HTTRACE(CORE_TRACE, "Net Object.. No object to kill\n");
2.23      frystyk   996:     return NO;
                    997: }
                    998: 
                    999: /*     HTNet_killAll
                   1000: **     -------------
2.74      frystyk  1001: **     Kills all registered net objects by calling the call
2.23      frystyk  1002: **     back function with a request for closing the connection. We do not
                   1003: **     remove the HTNet object as it is done by HTNet_delete().
                   1004: **     Returns OK if success, NO on error
                   1005: */
                   1006: PUBLIC BOOL HTNet_killAll (void)
                   1007: {
2.103     frystyk  1008:     HTTRACE(CORE_TRACE, "Net Object.. Kill ALL Net objects!!!\n"); 
2.74      frystyk  1009:     if (NetTable) {
                   1010:        HTList * cur = NULL;
                   1011:         HTNet * pres = NULL;
                   1012:        int cnt;
2.100     frystyk  1013:        for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74      frystyk  1014:            if ((cur = NetTable[cnt])) { 
2.105     kahan    1015:                while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL) {
                   1016:                    HTNet_kill(pres);
                   1017:                    cur = NetTable[cnt];
                   1018:                }
2.74      frystyk  1019:            }
2.25      frystyk  1020:        }
2.74      frystyk  1021:        return YES;
2.25      frystyk  1022:     }
2.103     frystyk  1023:     HTTRACE(CORE_TRACE, "Net Object.. No objects to kill\n");
2.74      frystyk  1024:     return NO;
2.23      frystyk  1025: }
2.38      frystyk  1026: 
                   1027: /* ------------------------------------------------------------------------- */
2.59      frystyk  1028: /*                         Connection Specifics                             */
                   1029: /* ------------------------------------------------------------------------- */
                   1030: 
2.74      frystyk  1031: /*     HTNet_priority
                   1032: **     --------------
                   1033: **     Get the current priority of the Net object
                   1034: */
                   1035: PUBLIC HTPriority HTNet_priority (HTNet * net)
                   1036: {
2.81      frystyk  1037:     return (net ? net->event.priority : HT_PRIORITY_INV);
2.74      frystyk  1038: }
                   1039: 
                   1040: /*     HTNet_setPriority
                   1041: **     -----------------
                   1042: **     Set the current priority of the Net object
                   1043: **     This will change the priority next time the thread is blocked
                   1044: */
                   1045: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
                   1046: {
                   1047:     if (net) {
2.81      frystyk  1048:        net->event.priority = priority;
2.74      frystyk  1049:        return YES;
                   1050:     }
                   1051:     return NO;
                   1052: }
                   1053: 
2.59      frystyk  1054: /*     HTNet_Persistent
                   1055: **     ----------------
                   1056: **     Check whether the net object handles persistent connections
                   1057: **     If we have a DNS entry then check that as well.
                   1058: */
                   1059: PUBLIC BOOL HTNet_persistent (HTNet * net)
                   1060: {
                   1061:     return (net && HTHost_isPersistent(net->host));
                   1062: }
                   1063: 
                   1064: /*     HTNet_persistent
                   1065: **     ----------------
                   1066: **     Set the net object to handle persistent connections
                   1067: **     If we also have a DNS entry then update that as well
                   1068: */
2.74      frystyk  1069: PUBLIC BOOL HTNet_setPersistent (HTNet *               net,
                   1070:                                 BOOL                   persistent,
                   1071:                                 HTTransportMode        mode)
2.59      frystyk  1072: {
                   1073:     if (net) {
2.81      frystyk  1074:        BOOL result = HTHost_setPersistent(net->host, persistent, mode);
2.103     frystyk  1075:        HTTRACE(CORE_TRACE, "Net Object.. Persistent connection set %s %s\n" _ 
                   1076:                    persistent ? "ON" : "OFF" _ 
2.74      frystyk  1077:                    result ? "succeeded" : "failed");
2.81      frystyk  1078:        return result;
2.59      frystyk  1079:     }
                   1080:     return NO;
                   1081: }
                   1082: 
2.66      frystyk  1083: /*
                   1084: **     Context pointer to be used in context call back function
                   1085: */
                   1086: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
                   1087: {
                   1088:     if (net) {
                   1089:        net->context = context;
                   1090:        return YES;
                   1091:     }
                   1092:     return NO;
                   1093: }
                   1094: 
                   1095: PUBLIC void * HTNet_context (HTNet * net)
                   1096: {
                   1097:     return net ? net->context : NULL;
                   1098: }
2.38      frystyk  1099: 
                   1100: /*
2.60      frystyk  1101: **  Get and set the socket number
                   1102: */
                   1103: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
                   1104: {
2.81      frystyk  1105:     if (net && net->host && net->host->channel) {
                   1106:        HTChannel_setSocket(net->host->channel, sockfd);
2.60      frystyk  1107:        return YES;
                   1108:     }
                   1109:     return NO;
                   1110: }
                   1111: 
                   1112: PUBLIC SOCKET HTNet_socket (HTNet * net)
                   1113: {
2.81      frystyk  1114:     return (net && net->host && net->host->channel ? HTChannel_socket(net->host->channel) : INVSOC);
2.69      frystyk  1115: }
                   1116: 
                   1117: /*
                   1118: **  Get and set the HTRequest object
                   1119: */
                   1120: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
                   1121: {
                   1122:     if (net && request) {
                   1123:        net->request = request;
                   1124:        return YES;
                   1125:     }
                   1126:     return NO;
                   1127: }
                   1128: 
                   1129: PUBLIC HTRequest * HTNet_request (HTNet * net)
                   1130: {
                   1131:     return (net ? net->request : NULL);
2.60      frystyk  1132: }
                   1133: 
                   1134: /*
2.59      frystyk  1135: **  Get and set the HTChannel object
2.55      frystyk  1136: */
2.59      frystyk  1137: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55      frystyk  1138: {
2.81      frystyk  1139:     return (net && channel) ? HTHost_setChannel(net->host, channel) : NO;
2.55      frystyk  1140: }
                   1141: 
2.59      frystyk  1142: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55      frystyk  1143: {
2.81      frystyk  1144:     return net ? HTHost_channel(net->host) : NULL;
2.59      frystyk  1145: }
                   1146: 
                   1147: /*
                   1148: **  Get and set the HTHost object
                   1149: */
                   1150: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
                   1151: {
                   1152:     if (net && host) {
                   1153:        net->host = host;
                   1154:        return YES;
                   1155:     }
                   1156:     return NO;
                   1157: }
                   1158: 
                   1159: PUBLIC HTHost * HTNet_host (HTNet * net)
                   1160: {
                   1161:     return (net ? net->host : NULL);
                   1162: }
                   1163: 
                   1164: /*
                   1165: **  Get and set the HTdns object
                   1166: */
                   1167: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
                   1168: {
                   1169:     if (net && dns) {
2.81      frystyk  1170:        net->host->dns = dns;
2.59      frystyk  1171:        return YES;
                   1172:     }
                   1173:     return NO;
                   1174: }
                   1175: 
                   1176: PUBLIC HTdns * HTNet_dns (HTNet * net)
                   1177: {
2.81      frystyk  1178:     return (net ? net->host->dns : NULL);
2.59      frystyk  1179: }
                   1180: 
2.81      frystyk  1181: PUBLIC BOOL HTNet_setProtocol (HTNet * net, HTProtocol * protocol)
                   1182: {
                   1183:     if (net && protocol) {
                   1184:        net->protocol = protocol;
                   1185:        return YES;
                   1186:     }
                   1187:     return NO;
                   1188: }
                   1189: 
                   1190: PUBLIC HTProtocol * HTNet_protocol (HTNet * net)
2.72      frystyk  1191: {
2.81      frystyk  1192:     return (net ? net->protocol : NULL);
2.72      frystyk  1193: }
2.59      frystyk  1194: 
2.86      frystyk  1195: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
                   1196: {
                   1197:     if (net && tp) {
                   1198:        net->transport = tp;
                   1199:        return YES;
                   1200:     }
                   1201:     return NO;
                   1202: }
                   1203: 
                   1204: PUBLIC HTTransport * HTNet_transport (HTNet * net)
                   1205: {
                   1206:     return (net ? net->transport : NULL);
                   1207: }
                   1208: 
                   1209: PUBLIC BOOL HTNet_preemptive (HTNet * net)
                   1210: {
                   1211:     return (net ? net->preemptive : NO);
                   1212: }
                   1213: 
2.59      frystyk  1214: /*
                   1215: **     Create the output stream and bind it to the channel
                   1216: **     Please read the description in the HTIOStream module on the parameters
                   1217: */
2.81      frystyk  1218: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * me, void * param, int mode)
2.59      frystyk  1219: {
2.81      frystyk  1220:     if (me && me->host && me->host->channel && me->transport) {
                   1221:        HTTransport * tp = me->transport;
                   1222:        HTChannel * ch = me->host->channel;
                   1223:        HTOutputStream * output = (*tp->output_new)(me->host, ch, param, mode);
2.74      frystyk  1224:        HTChannel_setOutput(ch, output);
2.59      frystyk  1225:        return output;
                   1226:     }
2.103     frystyk  1227:     HTTRACE(CORE_TRACE, "Host Object.. Can't create output stream\n");
2.59      frystyk  1228:     return NULL;
2.81      frystyk  1229: }
                   1230: 
2.87      frystyk  1231: PUBLIC HTEvent * HTNet_event (HTNet * net)
2.81      frystyk  1232: {
2.87      frystyk  1233:     return net ? &net->event : NULL;
                   1234: }
                   1235: 
                   1236: PUBLIC BOOL HTNet_setEventParam (HTNet * net, void * eventParam)
                   1237: {
2.81      frystyk  1238:     if (net) return HTEvent_setParam(&net->event, eventParam);
                   1239:     return NO;
                   1240: }
                   1241: 
2.87      frystyk  1242: PUBLIC void * HTNet_eventParam (HTNet * net)
2.81      frystyk  1243: {
2.87      frystyk  1244:     return net ? net->event.param : NULL;
2.81      frystyk  1245: }
                   1246: 
                   1247: PUBLIC BOOL HTNet_setEventCallback(HTNet * net, HTEventCallback * cbf)
                   1248: {
                   1249:     if (net) return HTEvent_setCallback(&net->event, cbf);
                   1250:     return NO;
                   1251: }
                   1252: 
                   1253: PUBLIC HTEventCallback * HTNet_eventCallback(HTNet * net)
                   1254: {
                   1255:     return net->event.cbf;
                   1256: }
                   1257: 
                   1258: PUBLIC BOOL HTNet_setEventPriority(HTNet * net, HTPriority priority)
                   1259: {
                   1260:     if (net) return HTEvent_setPriority(&net->event, priority);
                   1261:     return NO;
                   1262: }
                   1263: 
                   1264: PUBLIC HTPriority HTNet_eventPriority(HTNet * net)
                   1265: {
                   1266:     return net->event.priority;
                   1267: }
                   1268: 
                   1269: PUBLIC HTStream * HTNet_readStream(HTNet * net)
                   1270: {
                   1271:     if (!net) return NULL;
                   1272:     return net->readStream;
                   1273: }
                   1274: 
                   1275: PUBLIC BOOL HTNet_setReadStream (HTNet * net, HTStream * stream)
                   1276: {
                   1277:     if (net) {
                   1278:        net->readStream = stream;
                   1279:        return YES;
                   1280:     }
                   1281:     return NO;
2.96      frystyk  1282: }
                   1283: 
                   1284: /*
                   1285: **     Should we do raw byte count at the network or later?
                   1286: **     Normally it is later but in cases like FTP we need it
                   1287: **     in the raw form
                   1288: */
                   1289: PUBLIC BOOL HTNet_setRawBytesCount (HTNet * net, BOOL mode)
                   1290: {
                   1291:     if (net) {
                   1292:        net->countRawBytes = mode;
                   1293:        return YES;
                   1294:     }
                   1295:     return NO;
                   1296: }
                   1297: 
                   1298: PUBLIC BOOL HTNet_rawBytesCount (HTNet * net)
                   1299: {
                   1300:     return (net && net->countRawBytes);
2.55      frystyk  1301: }

Webmaster