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

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

Webmaster